Search code examples
reactjsreact-hooksuse-statererendermutated

change in state does not re-renders the component


const [list, setList] = useState([]);
useEffect(() => {
        const getData = async () => {
            let storeList = [];
            for (let i = 0; i<50; i++) {
                try {   
                    const token = await contract.methods.tokenOfOwnerByIndex(accountId , i).call();
                    let data = await contract.methods.tokenURI(token).call();
                    const receivedData = await fetch(data);
                    let jsonData = await receivedData.json();
                    storeList.push(jsonData);
                    setList(storeList);
                } catch(error) {
                    cogoToast.error(`Error caused in fetching data of ${i} number token`);
                }
            }
        };
        if (contract) getData();
    }, [contract]);

the initial state of "list" is empty. When the loop is run for 1st time and the list is updated for the first time, the component re-renders, but after that, even though the state is changing the component does not re-render.

Ideally, the component should re-render when the state changes.


Solution

  • You're mutating the array that already exists, not creating a new one. When you set state in a function component, react does a === between the old state and the new state. If they're the same, it skips rendering.

    To fix this, create a new array and set state with that:

    let jsonData = await receivedData.json();
    setList(prev => [...prev, jsonData]);