1

I am using React useState to declare my object:

    const [results, setResults] = useState();
  console.log(results);

In same file I am returning React component and I am passing it some props:

 <Table
          data={results ? results.Companies : []}
          setData={(newArr) => {
            let newResults = results;
            newResults.Companies = newArr.slice(0);
            console.log(newResults);
            return setResults(newResults);
          }}
        />

P.S.: Keep in mind that I am passing to data only results.Companies which is array.

In this Table component I am changing the results.Companies property:

props.setData(arr);

So when it triggers function in Table component:

setData={(newArr) => {
                let newResults = results; // I am assigning to newResults current result state
                newResults.Companies = newArr.slice(0); // I am replacing newResults.Companies with new array I want to pass
                console.log(newResults); // HERE is the desired results output
                return setResults(newResults);
              }}

The newResults variable is exactly the result I want to be passed to setResutlts. But this setting does not trigger re-rendering and this console.log(results) for example is not called. Why it is not trigger after I am passing new value to setResults()

3
  • 1
    can you make a codesandbox? Commented Jun 19, 2020 at 8:54
  • @RedBaron It's kind of complicated items and code. I am fetching initial results from API where I am using token and so on... Commented Jun 19, 2020 at 8:55
  • but if you make a simplified version with mocked data then it should work Commented Jun 19, 2020 at 8:57

1 Answer 1

3

As setData is a callback used by Table.

You have closures on results and you mutate state which is an anti-pattern.

Never mutate this.state directly, as calling setState() afterward may replace the mutation you made. Treat this.state as if it were immutable.

Due closures you keep calling setData with the last value of results upon its initialization, and by mutating the state you actually don't update state as by how setState works.

After understanding what closures are, you should refactor the code to use functional updates:

const setData = (newArr) => {
  setResults((prev) => {
    let newResults = {...prev, Companies: newArr.slice(0)};
    return newResults;
  });
}
<Table setData={setData}/>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.