简体   繁体   中英

How do I update State inside of a while loop in React

Say I have this code.

var s = [1,2,3,4,5,6,7,8,9,0];
const[arr,setArr]=useState(s);
while(arr.length != 0){
    setArr(arr.splice(0,1));
    console.log(arr); //This returns [2,3,4,5,6,7,8,9,0] and [3,4,5,6,7,8,9,0] and so on until []
}

I return {arr.length} at the end of the functionanl component. However, it first renders 10, and waits till the whole while loop is run and then renders 1. All the numbers inbettween are simply skipped.

I kind of understand why this happens, but is there anyway I can show all the lengths? I have a sleep function that takes milliseconds and halts the program for that time, if it is of any use in order to make sure the user can see the rendered lengths for a reasonable time.

Thanks in advance!

Assuming this is a functional component (I'm guessing you meant useState , not setState , in const[arr,setArr]=setState(s); ), you need to let the component render each state before setting the next. Otherwise, all the state updates get batched together and the component only renders again when they're all done.

For instance:

function Example() {
    const [arr, setArr] = useState([1,2,3,4,5,6,7,8,9,0]);
    // Set up a timer on mount, remove it on dismount and when
    // we run out of values to show
    useEffect(() => {
        const handle = setInterval(() => {
            // Note useing the callback function, so `arr` isn't stale
            // in this callback
            setArr(a => {
                if (a.length) {
                    // Update the array, dropping the first entry
                    return a.slice(1);
                }
                // No more entries, stop the timer
                clearInterval(handle);
                return a;
            });
        }, 500);
        return () => clearInterval(handle);
    }, []);
    return <div>{arr.join()}</div>;
}

I think you can use useEffect hook

Each time, we change arr , hook will be called with some timeout

const SHOW_TIMEOUT = 300;
var s = [1,2,3,4,5,6,7,8,9,0];

const [arr, setArr] = useState(s);

useEffect(() => {
  const timeoutId = setTimeout(() => setArr(arr.slice(1)), SHOW_TIMEOUT);

  return () => clearTimeout(timeoutId); // also need to stop timeout in case of unmount
}, [arr]);

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