首页 > 解决方案 > 状态不会在异步函数中更新

问题描述

你能帮我理解为什么当我在第一个 useEffect 中调用两个异步函数时我的状态没有更新吗?在我不知道哪个先出现(API1 或 API2)的情况下,处理异步数据的最佳方法是什么?

谢谢!

const MyClass = () => {
    const [myState, setMyState] = useState([]);

    useEffect(() => {
        callApi1();
        callApi2();
    }, []);

    const callApi1 = () => {
        fetch(...).then(result => {
            // the result of API 1 always comes first and result is not empty
            setMyState(result);
        )};
    }

    const callApi2 = () => {
        fetch(...).then(result => {
            // the result of API 2 always comes 5 - 10 seconds after the API 1
            console.log(myState) => [], WHY?
        });
    }
}

标签: javascriptreactjsreact-hooksuse-effectuse-state

解决方案


(1.) “……为什么我的状态没有更新……”

您的状态更新,但回调函数捕获myState(作为闭包)的旧状态。这意味着myState回调函数内部将始终与创建函数时保持一致。(并且它仅在调用 callApi2() 时创建。)

您无法在异步回调中访问当前的最新状态。

(2.) “......在我不知道哪个先出现的情况下处理异步数据的最佳方式”

这取决于您的用例。
一般来说,你会从你的回调中设置一些状态(例如你的setMyState(result)),你的程序的不同部分会根据这些状态做一些其他的事情,例如useEffect(()=>{ /* do something */ }, [ myState ])

例如:

const MyClass = () => {
    const [myState, setMyState] = useState([]);
    const [myState2, setMyState2] = useState([]);
    const [allDone, setAllDone] = useState(false);

    useEffect(() => {
        callApi1();
        callApi2();
    }, []);

    useEffect(() => {
        console.log( 'myState/myState2:', myState, myState2);
        if( myState.length && myState2.length ){
            setAllDone(true);
        }
    }, [ myState, myState2 ]);

    const callApi1 = () => {
        fetch(...).then(result => {
            setMyState(result);
        )};
    }

    const callApi2 = () => {
        fetch(...).then(result => {
            setMyState2(result);
        });
    }
}

推荐阅读