Home > Software engineering >  re-render useState for each object in an array
re-render useState for each object in an array

Time:08-01

When I click the MultipleComponent button, all logs in the function return null.

The second time I click it, it returns the previous values.

How can I get the current status in each log within the map function?

When I call the function in the useEffect hook, useEffect runs after the first render. I don't want it to run after the first render.

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import { observer } from "mobx-react-lite";

function App() {
  const [component, setComponent] = useState([]);

  useEffect(() => {});

  const newArray = [1, 2, 3];

  const Test = observer(() => {
    return (
      <div>
        <p>Test</p>
      </div>
    );
  });

  const Test2 = observer(() => {
    return (
      <div>
        <p>Test2</p>
      </div>
    );
  });

  const Test3 = observer(() => {
    return (
      <div>
        <p>Test3</p>
      </div>
    );
  });

  function MultipleComponent() {
    newArray.map(async (x) => {
      if (x === 1) {
        setComponent((ps) => [...ps, Test]);
        console.log(component);
      } else if (x === 2) {
        setComponent((ps) => [...ps, Test2]);
        console.log(component);
      } else {
        setComponent((ps) => [...ps, Test3]);
        console.log(component);
      }
    });
  }

  return (
    <div>
      {component.map((Input, index) => (
        <Input components={component} key={index} />
      ))}
      <button onClick={() => setComponent([...component, Test])}>
        Single Component
      </button>
      <button onClick={() => MultipleComponent()}>Multiple Component</button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

codensadbox: https://codesandbox.io/s/react-hooks-useeffect-forked-shxvl6

CodePudding user response:

When I click the MultipleComponent button, all logs in the function return null.

The second time I click it, it returns the previous values.

React state updates are asynchronous and do not update any values in the current scope. They trigger a render, and then your component executes again with that new state.

See this for more info: The useState set method is not reflecting a change immediately


How can I get the current status in each log within the map function?

You can't get the state that has been changed until the next render, but you don't need to because you have the value that you set. Just use that if you need to. For example:

setComponent((ps) => {
  const newState = [...ps, Test];
  console.log(newState);
  return newState;
});

When I call the function in the useEffect hook, useEffect runs after the first render. I don't want it to run after the first render.

Your effect has no dependencies, which means that it will run after every render. Just pass an array of dependencies to the effect in order to only execute it when those change. If you pass an empty array, then it will only every execute once.

useEffect(() => console.log('I run only once'), []);

See the docs on useEffect for more: https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects

CodePudding user response:

Hi as per the documentation "calling the set function does not change state in the running code". If you need to use the next state, you can save it in a variable before passing it to the set function.

Here is a link of your updated code.

https://codesandbox.io/s/react-hooks-useeffect-forked-m7ipwb?file=/src/index.js

When I call the function in the useEffect hook, useEffect runs after the first render. I don't want it to run after the first render.

By default, Effects run after every render. You can tell React to skip unnecessarily re-running the Effect by specifying an array of dependencies as the second argument to the useEffect call. Start by adding an empty [] array

  • Related