简体   繁体   中英

Using setTimeout to force state update in React

I'm building a React App and having issues with re-renders when state is updated. Basicly I just manipulate a bunch of arrays and need things to re-render inside the aplication.

So I tried to put a setTimeout before the change of state and "Voilà," it worked, now I have a lot of setTimeouts updating states and I know this is not the best way to do it, so my question is: how can I do this without using the timeouts?

The example below is a function when on click update a value in a object inside an array:

const documentCopy = selectedDocument;
documentCopy.pages.find((page) =>
  page.id === id
    ? page.active === true
      ? (page.active = false)
      : (page.active = true)
    : null,
);
setTimeout(() => {
  setSelectedDocument(null);
  setSelectedDocument(documentCopy);
}, 1);

And this is the rendering implementation:

{selectedDocument && selectedDocument.pages.map((page, i) => (
        <IconButton
            key={page.id}
            onClick={() => handleCheckImage(page.id)}
        >
            <img src={page.img}
                width='85'
                height='120'
                alt={'document'}
            />
            <Checkbox className={
                page.active
                    ? classes.imageBox
                    : classes.imageBoxHidden
                }
                checked={page.active}
                name={page.id}
                color='primary'
            />
        </IconButton>
    )
)}

Basically I just need to click on an image and when I click on the checkbox for that particular image it gets checked or unchecked and displayed on the screen.

Sorry for my, not great, english and any tips are welcome.

Ty all in advance.

When react decideds to do a rerender because of a state change it looks at the previous state and the new state. It then decides if these are different and rerenders the component. If the previous and new state are not different it doesnt rerender. This works for primitive types because when they are saved a new section in memory is assigned to the value.

However it doesnt work as expected when comparing Arrays. This has to do with the way that Arrays are stored in memory. They are stored by reference instead of creating a new value in memory. This is shown in the code below, you would expect the console.log to print false, but it actually prints true. This is because arr1 and arr2 are actually the same array because they point to the same value in memory.

 const arr1 = ['dog', 'cat', 'bird']; const arr2 = arr1; arr2.push('fish'); console.log(arr1 === arr2);

As for react a way to get around this is you can create a new array when you set it in state. So in your case you could do something like this to get a rerender. The code creates a brand new array / value in memory containing your original arrays data.

 setSelectedDocument([...documentCopy]);

The reason the timeout is working is because you are setting the value of the state to null and then to the page. So React sees these two as different.

Hope this helps, further reading if you are interested: https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM