Search code examples
reactjsreact-hooksreact-componentreact-statereact-state-management

How to setState of an array of objects in functional components


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...


Solution

  • These are two ways of solving this.

    First one:

    • Following the approach for the weekdays and data 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 of indexes. This array will contain the indexes to the days objects that should be selected in the weekdays array. (You can leave the weekdays 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!