-2

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

mirzaei
  • 17
  • 5
  • 2
    You can't access the updated state immediately after setting it so every callback in the map sees the same `messagesList`. Also you're using `map()` as a `forEach()` here. `map()` the array once and then call `setState` with the result. – pilchard Oct 23 '22 at 11:02
  • Thank you, if I use forEach() instead of map, the problem will be solved? – mirzaei Oct 23 '22 at 11:45
  • 1
    No, you can't call `setState` repeatedly in a loop and expect to access the updated state from previous iterations. – pilchard Oct 23 '22 at 12:02
  • so which approach do you prefer I use? – mirzaei Oct 23 '22 at 12:09
  • See my answer for an example – pilchard Oct 23 '22 at 12:09
  • Thank you, your example was useful and I used it, I have a question about a very simple example, what do you think about the below code: ` import { useState } from "react"; export default function App() { const [isLoading, setIsLoading] = useState(false); const handleClick = () => { setIsLoading(true); console.log(isLoading); }; return (
    ); } ` how can I access immediatly in this example ? for example the log can not access to the updated state and it logs the default state
    – mirzaei Oct 24 '22 at 12:16
  • You can never access it immediately, it will only ever be available the next render cycle. See [The useState set method is not reflecting a change immediately](https://stackoverflow.com/questions/54069253/the-usestate-set-method-is-not-reflecting-a-change-immediately) – pilchard Oct 24 '22 at 12:51

1 Answers1

0

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
]);
pilchard
  • 12,414
  • 5
  • 11
  • 23