Reputation: 55
I have a Home Component that contains 2 hardcoded routes and 2 mapped ones, I'm parsing the plan object to the Plan component.
<Routes>
<Route path='/' element={<Heading>index</Heading>}/>
<Route path='/profile' element={<Profile />}/>
{user &&
user.workoutPlans.map((plan, index) => (
plan._id && <Route path={'/' + plan._id} key={index} element={<Plan plan={plan} />} />
))}
</Routes>
The Plan Component displays the plan title and contains a section where it maps an array of days to DayCards
<Heading size='2xl' mr={-3}>{plan.title}</Heading>
<Flex direction='column'>
{plan.days.map((day, index) => (
day._id && <DayCard planId={plan._id} day={day} key={index} />
))}
</Flex>
If I refresh then go to the route app.com/plan1id I get the correct list of days [day1, day2, day3, day4, day5] + Heading: Plan1
If I refresh then go to the route app.com/plan2id I get the correct list of days [other1, other2, other3] + Heading: Plan2
But if I then go from app.com/plan2id to app.com/plan1id I get a messed up list of days [other1, other2, other3, day4, day5] + Heading: Plan1
Its the same in reverse order
But if I refresh then go to the route app.com/plan1id then got to app.com/profile then to app.com/plan2id it works correctly returning [other1, other2, other3] + Heading: Plan2
The app state stays the same the entire time and the plan data is being parsed in correctly as far as I can tell because plan.title always displays correctly
Any ideas about why this is happing would be greatly appreciated
Upvotes: 1
Views: 41
Reputation: 203062
Don't use the array index as a React key.
When switching plans the route changes, but the Plan
component remains mounted and only the plan
prop value updates. This triggers a rerender. But since the days are using an array index as the React key, the key doesn't change value. Day index 2 in plan "A" is equal to day index 2 in plan "B".
You should instead use a value that is intrinsic to the data being mapped. GUIDs make for great React keys. I suggest using day._id
as the React key, assuming these are unique.
<Flex direction='column'>
{plan.days
.filter(day => day._id)
.map((day) => <DayCard planId={plan._id} day={day} key={day._id} />)
}
</Flex>
May as well correct the routing code too for the Plan
component.
<Routes>
<Route path='/' element={<Heading>index</Heading>} />
<Route path='/profile' element={<Profile />} />
{user?.workoutPlans
.filter(plan => plan._id)
.map((plan) => (
<Route
path={`/${plan._id}`}
key={plan._id}
element={<Plan plan={plan} />}
/>
))
}
</Routes>
Upvotes: 2
Reputation: 1248
You should also use exact props with Route <Heading>
otherwise when you navigate to /profile
or other routes then Heading will first get call.
For more reference check this link https://stackoverflow.com/a/49162423/4554623
<Routes>
<Route exact path='/' element={<Heading>index</Heading>} />
<Route path='/profile' element={<Profile />} />
{user?.workoutPlans
.filter(plan => plan._id)
.map((plan) => (
<Route
path={`/${plan._id}`}
key={plan._id}
element={<Plan plan={plan} />}
/>
))
}
</Routes>
Upvotes: 0