0

I have a button in react and when it is pressed, I would like to print the content of 2 concatenated arrays. This is the code for it

const QueryCalibDetail = ({result}) => {
    const [success, setSuccess] = useState('')
    const [raws, setRaws] = useState([])
    
    const handleClick = async (e) => {
        await axios.get('/api/rawsRoute/' + result.rawID)
        .then ((json) => {
            setRaws(json.data.raws)
        })
        
        const allFiles = result.config_files.concat(raws)

        for (const fileID of allFiles) {
               console.log(fileID)
        }

To explain this code, QueryCalibDetail takes a prop called result which is a json and has fields _id (an id), rawID (an id) and config_files (an array of ids). I use axios to get an element from a database with the id rawID. The fetch returns a json which has a field raws, an array of ids. Now I have 2 arrays of ids that I would like to concatenate and iterate through and log to console. However, the state raws remains an empty array even after setRaws has been called, and only the array provided by result.config_files is printed. The concatenated array only gets printed when I click the button a second time.

This has been a recurring issue in my project, and I never understood why useState doesn't immediately update the state, or how to fix the issue. Can someone explain what I'm supposed to do in this scenario, since it seems to happen rather often and every time I don't know how to handle it.

Ruo
  • 77
  • 7
  • 1
    Does this answer your question? [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) – luk2302 Jun 02 '23 at 19:20
  • The duplicate both explains why this behavior occurs as well as what to do to fix it. One thing to note for example is that `raws` is `const`, it *cannot* change. – luk2302 Jun 02 '23 at 19:21
  • @luk2302 From what I understood of the article, I should use a useEffect hook like this ```useEffect (() => { allFiles = result.config_files.concat(raws) }, [raws])``` But that isn't working either – Ruo Jun 02 '23 at 19:34
  • You seem to misunderstanding how state is supposed to managed and handed around. Sure the snippet you posted in the comment works but it makes no sense because what is `allFiles`!? That is state yet again that either needs to be managed using `useState` or instantly used where you set its value. You **cannot** change the value in `useEffect` and expect it to be visible outside of it because that is not how state management and rendering works. – luk2302 Jun 05 '23 at 07:57

1 Answers1

-1

One of the reasons why the state raws remains an empty array even after setRaws has been called is because React batches state updates. This means that React does not update the state immediately, but instead waits until the next render cycle. This is done for performance reasons.

You can choose to use the useEffect hook to force React to update the state immediately. My approach would be as in the code below

    const QueryCalibDetail = ({result}) => {
    const [success, setSuccess] = useState('')
    const [raws, setRaws] = useState([])

    const handleClick = async (e) => {
        await axios.get('/api/rawsRoute/' + result.rawID)
        .then((json) => {
            setRaws(json.data.raws)
        })

        useEffect(() => {
            const allFiles = result.config_files.concat(raws)
            for (const fileID of allFiles) {
                console.log(fileID)
            }
        }, [raws])
    }

    return (
        <div>
            <button onClick={handleClick}>Click Me</button>
        </div>
    );
    };

The useEffect hook is a powerful tool that can be used to control when React updates the state. It can be used to fix issues like the one you were experiencing, and it can also be used to perform other tasks, such as fetching data from an API.

I hope this helps!

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 03 '23 at 07:15