I am trying to setState of an Array of objects when component load. state of the component is:
const [weekdays, setWeekdays] = useState([{
day: 'S',
fullName: 'Sunday',
select: false
},
{
day: 'M',
fullName: 'Monday',
select: false
},
{
day: 'T',
fullName: 'Tuesday',
select: false
},
{
day: 'W',
fullName: 'Wednesday',
select: false
},
{
day: 'T',
fullName: 'Thursday',
select: false
},
{
day: 'F',
fullName: 'Friday',
select: false
},
{
day: 'S',
fullName: 'Saturday',
select: false
}])
The array which I am trying to setState is: data
I am trying in this way to setState when page loads:
useEffect(() => {
{
(data?.length > 0)
?
setWeekdays([weekdays => (
{
...weekdays,
...data?.map((item) => { return { day: item.day, fullName:item.fullName, select:true } }),
})])
:
setWeekdays([...weekdays])
}
}, [data]);
Thanks...
CodePudding user response:
These are two ways of solving this.
First one:
Following the approach for the
weekdays
anddata
structure you have in your question code - with each one as an array of objects:useEffect(() => { const newWeekdays = []; if (data?.length > 0) { setWeekdays((weekdays) => { for (const item in data) { if (data[item] !== "") { newWeekdays.push({ ...weekdays[item], select: true }); } else { newWeekdays.push({ ...weekdays[item] }); } } return newWeekdays; }); } }, [data]);
Second one: (which I think is better)
You can have the
data
as a simple array ofindexes
. This array will contain the indexes to the days objects that should be selected in theweekdays
array. (You can leave theweekdays
structure as it is in your question.)So now this how the data array looks like:
const data = [0, 2, 4]; //Sunday, Tuesday, Thursday
And this is how you can update the selected indexes to
select:true
:useEffect(() => { if (data?.length > 0) { setWeekdays((weekdays) => { const newWeekdays = weekdays.map((item, index) => { if (data.includes(index)) { return { ...item, select: true }; } return { ...item }; }); return newWeekdays; }); } }, [data]);
Hope this helps. Good luck!
CodePudding user response:
You created weekdays
as an array, but when you call setWeekdays
you are returning an object. You need to make sure your new value is the same structure.
That said, your current data structure is not very efficient. If I understand correctly, you simply want to store which set of days are selected. You would do better to have an object instead of an array.
const [weekdays, setWeekdays] = useState({
sunday: {
day: 'S',
fullName: 'Sunday',
select: false
},
monday: {
day: 'M',
fullName: 'Monday',
select: false
},
tuesday: {
day: 'T',
fullName: 'Tuesday',
select: false
},
wednesday: {
day: 'W',
fullName: 'Wednesday',
select: false
},
thursday: {
day: 'T',
fullName: 'Thursday',
select: false
},
friday: {
day: 'F',
fullName: 'Friday',
select: false
},
saturday: {
day: 'S',
fullName: 'Saturday',
select: false
}
})
const data = ['monday', 'wednesday', 'friday']
useEffect(() => {
setWeekdays(weekdays => ({
...weekdays,
...data
.map(key => ({[key]: {...weekdays[key], selected: true}}))
.reduce((prev, next) => Object.assign(prev, next))
})
}, [data]);