Skip to content
Advertisement

why does setState runs once inside the map?

I have an array of objects which I want to map it and set the objects into the messagesList state, but only the last object is set. Actually, I want the setting to be done as soon as the map is executed but here it is done only once and the last item of the array is set.

You can see the codes:

        const steps = [
          {
            id: "ab4acc83-f732-443a-9c05-f6fee37f9116",
            order: 1,
            schema: {
              answer: "answer 1",
              process: "display",
              outputType: "text",
            },
            FlowId: "c0967d44-a218-443e-afd5-5f113ad4d48e",
            createdAt: "2022-10-23T05:35:05.235Z",
            updatedAt: "2022-10-23T05:35:05.235Z",
          },
          {
            id: "ab4acc83-f732-443a-9c05-f6fee37f9116",
            order: 1,
            schema: {
              answer: "answer 2",
              process: "display",
              outputType: "text",
            },
            FlowId: "c0967d44-a218-443e-afd5-5f113ad4d48e",
            createdAt: "2022-10-23T05:35:05.235Z",
            updatedAt: "2022-10-23T05:35:05.235Z",
          },
        ];
        steps.map((step) => {
          setMessagesList([
            ...messagesList,
            {
              dataType: "text",
              item: {
                id: uuidv4(),
                type: "sender",
                message: "Question",
              },
            },
            {
              dataType: "text",
              item: {
                id: uuidv4(),
                type: "reciever",
                message: step.schema.answer,
              },
            },
          ]);
        });

Now MessagesList List only consists the last item of the array

Advertisement

Answer

As mentioned in my comment above you can’t call setState repeatedly in a loop and expect to access the updated state from previous iterations, aside from being extremely inefficient.

Instead, map() the array once to the desired shape and then call setState once with the result. Here using flatMap() since you seem to be creating two objects for every object in the steps array.

const steps = [{ id: "ab4acc83-f732-443a-9c05-f6fee37f9116", order: 1, schema: { answer: "answer 1", process: "display", outputType: "text", }, FlowId: "c0967d44-a218-443e-afd5-5f113ad4d48e", createdAt: "2022-10-23T05:35:05.235Z", updatedAt: "2022-10-23T05:35:05.235Z", }, { id: "ab4acc83-f732-443a-9c05-f6fee37f9116", order: 1, schema: { answer: "answer 2", process: "display", outputType: "text", }, FlowId: "c0967d44-a218-443e-afd5-5f113ad4d48e", createdAt: "2022-10-23T05:35:05.235Z", updatedAt: "2022-10-23T05:35:05.235Z", },];

const updatedSteps = steps.flatMap((step) => (
  [
    {
      dataType: "text",
      item: {
        id: uuidv4(),
        type: "sender",
        message: "Question",
      },
    },
    {
      dataType: "text",
      item: {
        id: uuidv4(),
        type: "reciever",
        message: step.schema.answer,
      },
    },
  ]
));

setMessageList(prev => [
  ...prev,
  ...updatedSteps
]);
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement