为什么当我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
末尾的输出感到困惑。它没有显示更新的用户有两个原因,其中任何一个都足够了。:-(它们是:
-
console.log(userData)
发生在setuserData
调用之前,因为promise回调总是异步的。 -
userData
是Example
函数调用中的常量,其值不会更改。当状态更改时,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)
}
这个代码似乎对我有效,但我不确定如何使用它以同样的方式访问其他页面上的信息?