0

为什么当我 console.log(data) 是它记录数据时,但是当我尝试记录由 set state 设置的项目时,它是 null ?我不明白是不是因为在控制台记录之前没有时间更新?

  const [currentUser, setCurrentUser] = useState(null);
        const [pending, setpending] = useState(true);
        const [userData, setuserData] = useState({});

        useEffect(() => {
            Authentication.auth().onAuthStateChanged((user) => {
                setCurrentUser(user)
                setpending(false)
                localStorage.setItem('user', user.uid);
                console.log(localStorage.getItem('user'));
            });

            getData()

        }, []);

        const getData = () => {
            Authentication.firestore().collection('Health_data')
                .doc(localStorage.getItem('user'))
                .get()
                .then(doc => {
                    const data = doc.data();
                    localStorage.setItem('user_data', JSON.stringify(data));
                    setuserData(data)
                    console.log(data)
                }).catch(function (error) {
                    console.error("Error reading health", error);
                });
                console.log(userData)
        }
4

3 回答 3

3

我假设您对.console.log(userData);结尾处的输出感到困惑getData。它不显示更新的用户有两个原因,其中任何一个本身就足够了。:-) 他们是:

  1. console.log(userData)发生在调用之前setuserData因为 promise 回调总是异步的。

  2. userDataExample函数调用中的一个常量,它的值不会改变。当状态改变时,Example将再次被调用,并且 userData常量将包含更新的用户。let(请注意,它是否用or声明并不重要,无论const哪种方式,它实际上都是一个常量。)这些常量中的每一个都存在于一个执行上下文中,该上下文与创建的常量的特定调用相关联Example。Dan Abramov 的文章A中的更多内容完整指南useEffect(大约远不止useEffect)。

这是一个演示:

const { useState } = React;

const delay = ms => new Promise(resolve => setTimeout(resolve, ms));

let executionContext = 0;
const Example = () => {
    const contextNumber = ++executionContext;
    const [value, setValue] = useState(0);

    const log = msg => console.log(`[${contextNumber}]: ${msg}`);

    log(`Example called, value = ${value}`);
    
    const onClick = () => {
        log(`onClick`);
        delay(800)
        .then(() => {
            const newValue = Math.floor(Math.random() * 10000);
            log(`calling setValue(${newValue})...`);
            setValue(newValue);
            log(`value is still ${value} (reason #2)`);
        });
        log(`value is still ${value} (reason #1)`);
    };
    
    return (
        <div>
            {value}
            <div>
                <input type="button" onClick={onClick} value="Click Me" />
            </div>
        </div>
    );
}


ReactDOM.render(<Example/>, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>

于 2020-04-02T12:33:55.247 回答
1

如果您正在谈论此代码:

Authentication.firestore().collection('Health_data')
                .doc(localStorage.getItem('user'))
                .get()
                .then(doc => {
                    const data = doc.data();
                    localStorage.setItem('user_data', JSON.stringify(data));
                    setuserData(data)
                    console.log(data)
                }).catch(function (error) {
                    console.error("Error reading health", error);
                });
                console.log(userData)

问题是

Authentication.firestore().collection('Health_data')
                .doc(localStorage.getItem('user'))
                .get()

是异步执行,所以console.log(userData),有时会在Authentication调用之前执行,值是null.

所以你需要确保Authentication调用已经完成

于 2020-04-02T12:35:05.373 回答
0
if(userData !== null) {
    console.log(userData)
}

这段代码似乎对我有用,但我不确定如何使用它以同样的方式访问其他页面上的信息?

于 2020-04-02T12:45:00.480 回答