I'm developing a form for creating training programs and to show a week, I first create an array of all the days. What day gets rendered depends on the current day (state). The problem is that every time I change the current day, i.e. click another day-tab, the array seems to be reinitialized (I put a console.log
for each day in the array, as can be seen in the code).
I really hope to find a solution which creates all days, and then simply picks one from the array without creating the array all over again each time one day is accessed.
Do you have any suggestions?
I've tried (among other things): refactoring out components (before, there were no "WeekView", "DayView"), useMemo
-hook.
Source:
import React, { useContext } from 'react';
import { ProgramContext } from '../state/context';
import { setCurrentDay } from '../state/reducer';
import { Tabs, TabWindow, WindowTab } from '../styled';
import DayView from './DayView';
const WeekView: React.FC = () => {
const { state, dispatch } = useContext(ProgramContext);
const handleDayClick = (index: number) => () => {
if (index === state.currentDay) return;
dispatch(setCurrentDay(index));
};
const days = [...Array(state.daysPerWeek).keys()]
.map(i => i state.currentWeek * state.daysPerWeek)
.map(day => {
console.log(day);
return (
<DayView key={day} day={day} />
)
});
return (
<TabWindow>
<Tabs>
{[...Array(state.daysPerWeek).keys()].map(day => {
return (
<WindowTab
active={state.currentDay === day}
key={day}
onClick={handleDayClick(day)}
>
{`Dag ${(day % state.daysPerWeek) 1}`}
</WindowTab>
)
})}
</Tabs>
{days[state.currentDay]}
</TabWindow>
)
};
export default WeekView;
CodePudding user response:
Your problem is you initialize days
for every re-rendering of that component.
For a potential fix, you should add another state for days
, and only update days
when state.currentWeek
or state.daysPerWeek
gets changed.
import React, { useContext, useEffect, useState } from 'react';
import { ProgramContext } from '../state/context';
import { setCurrentDay } from '../state/reducer';
import { Tabs, TabWindow, WindowTab } from '../styled';
import DayView from './DayView';
const WeekView: React.FC = () => {
const [days, setDays] = useState([]);
const { state, dispatch } = useContext(ProgramContext);
const handleDayClick = (index: number) => () => {
if (index === state.currentDay) return;
dispatch(setCurrentDay(index));
};
useEffect(() => {
const updatedDays = [...Array(state.daysPerWeek).keys()]
.map(i => i state.currentWeek * state.daysPerWeek)
.map(day => {
console.log(day);
return (
<DayView key={day} day={day} />
)
});
setDays(updatedDays)
}, [state.currentWeek, state.daysPerWeek])
return (
<TabWindow>
<Tabs>
{[...Array(state.daysPerWeek).keys()].map(day => {
return (
<WindowTab
active={state.currentDay === day}
key={day}
onClick={handleDayClick(day)}
>
{`Dag ${(day % state.daysPerWeek) 1}`}
</WindowTab>
)
})}
</Tabs>
{days.length && days[state.currentDay]}
</TabWindow>
)
};
export default WeekView;