-1

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

  • It's not clear what you're asking. You have a `weekdays` array and each item in it have a `selected` field, then you get some `data` array which includes some of the weekdays and what you want to do is update the selected field to true for the days that are included in that data array. Is this your question? – Tehila Oct 12 '22 at 05:49
  • yes,exactly that is my question I want to update the selected fields –  Oct 12 '22 at 06:16
  • Why don't you do what @Trevin Avery said in the answer? Saving it as an object with key value pairs of : `{ sunday: {...} , moday: {...}}` instead of an array will make it much easier to update. – Tehila Oct 12 '22 at 06:23
  • 1
    Yes,I have tried but it gives TypeError: weekdays.map is not a function –  Oct 12 '22 at 06:30
  • Posted my answer to this. Hope it helps. – Tehila Oct 12 '22 at 07:11

2 Answers2

2

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!

Tehila
  • 917
  • 4
  • 19
  • This helped me.first one works perfectly without doing any changes....Thanks a lot for sharing your solution @Tehila –  Oct 12 '22 at 07:23
  • Happy it helped! Though I think the second one will be much easier to work with... But do as you like :) – Tehila Oct 12 '22 at 07:29
0

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]);
Trevin Avery
  • 2,751
  • 2
  • 20
  • 31