我在 react 本机应用程序中使用了很多 firestore 快照。我也在使用 React 钩子。代码如下所示:
useEffect(() => {
someFirestoreAPICall().onSnapshot(snapshot => {
// When the component initially loads, add all the loaded data to state.
// When data changes on firestore, we receive that update here in this
// callback and then update the UI based on current state
});;
}, []);
起初,我认为useState
是存储和更新 UI 的最佳钩子。但是,根据我的useEffect
钩子使用空依赖项数组设置的方式,当快照回调使用更新的数据触发并且我尝试使用新更改修改当前状态时,当前状态是未定义的。我相信这是因为关闭。我能够使用useRef
和这样的forceUpdate()
绕过它:
const dataRef = useRef(initialData);
const [, updateState] = React.useState();
const forceUpdate = useCallback(() => updateState({}), []);
useEffect(() => {
someFirestoreAPICall().onSnapshot(snapshot => {
// if snapshot data is added
dataRef.current.push(newData)
forceUpdate()
// if snapshot data is updated
dataRef.current.find(e => some condition) = updatedData
forceUpdate()
});;
}, []);
return(
// JSX that uses dataRef.current directly
)
我的问题是,我通过将useRef
与forceUpdate
一起使用而不是以不同的方式useState
来做到这一点是否正确?我必须更新useRef
钩子并在整个应用程序中调用forceUpdate()
似乎不对。尝试useState
时,我尝试将状态变量添加到依赖项数组中,但最终得到了无限循环。我只希望快照函数初始化一次,并且随着后端的变化(在 onSnapshot 回调中触发(随着时间的推移更新组件中的有状态数据。
如果将 useEffect 和 useState 结合起来会更好。UseEffect将设置和分离侦听器,useState可以只负责您需要的数据。
const [data, setData] = useState([]);
useEffect(() => {
const unsubscribe = someFirestoreAPICall().onSnapshot(snap => {
const data = snap.docs.map(doc => doc.data())
this.setData(data)
});
//remember to unsubscribe from your realtime listener on unmount or you will create a memory leak
return () => unsubscribe()
}, []);
然后,您只需从应用程序中的useState钩子中引用"数据"。
一个简单的useEffect对我有用,我不需要创建一个辅助函数或任何东西,
useEffect(() => {
const colRef = collection(db, "data")
//real time update
onSnapshot(colRef, (snapshot) => {
snapshot.docs.forEach((doc) => {
setTestData((prev) => [...prev, doc.data()])
// console.log("onsnapshot", doc.data());
})
})
}, [])
我发现在 onSnapshot(( 方法内部我无法访问状态(例如,如果我控制台.log(状态(,我会得到一个空值。
创建一个辅助函数,但我不确定这是否是 hack-y 解决方案,而是像这样:
[state, setState] = useState([])
stateHelperFunction = () => {
//update state here
setState()
}
firestoreAPICall.onSnapshot(snapshot => {
stateHelperFunction(doc.data())
})
使用可以使用set钩子上的回调来获取当前状态
const [state, setState] = useState([]);
firestoreAPICall.onSnapshot(snapshot => {
setState(prevState => { prevState.push(doc.data()) return prevState; })
})
上一页状态将具有当前状态值