为什么在使用setState(..)时console.log为null



为什么当我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)
}

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

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

  2. userDataExample函数调用中的常量,其值不会更改。当状态更改时,Example将再次被调用,并且newuserData常量中将包含更新的用户。(请注意,无论是用let还是const声明,它都是一个常量。)这些常量中的每一个都存在于执行上下文中,该上下文与创建该常量的Example的特定调用相关联。更多信息,请参阅Dan Abramov的文章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>

如果你谈论的是这个代码:

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调用已完成

if(userData !== null) {
console.log(userData)
}

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

最新更新