上下文:我有一个自定义钩子,用于获取Firestore文档。它监视文档更改,然后返回它和加载状态。我在另一个组件中使用了这个钩子。
问题::对钩子返回的状态值(loading
和document
)进行的更改不会触发使用钩子重新渲染并查看更新后的值的组件。
我的发现:其他自定义钩子可以正常工作并触发渲染,因此useDocument
钩子一定存在问题。如果另一个挂钩触发了重新渲染,则loading
才会最终更新。 loading
和document
的值确实可以在挂钩中按预期更新,但是仍然不会触发组件的重新渲染。
重要说明: useFirebase()
是在useDocument
中调用的一个挂钩,它的状态通过constate
库提升到上下文中。因此,从技术上讲,此挂钩是某些提供程序的使用者,该提供程序位于跟踪Firebase库的树的上方。这是为了避免不必要的网络呼叫。
export function useDocument() {
const { auth, firestore } = useFirebase() // asynchronously fetches firebase modules
const [loading, setLoading] = useState(true)
const [document, setDocument] = useState()
let unsubscribe = null
useEffect(() => {
let unsubscribe = null
const watchDocument = () =>
params?.query.onSnapshot(
(doc) => {
setDocument(doc.data() as T | undefined)
setLoading(false)
},
(err) => {
console.log(err)
setError(err.message)
}
)
if (firestore && auth?.currentUser) {
unsubscribe = watchDocument()
}
return () => {
unsubscribe && unsubscribe()
}
}, [firestore, auth?.currentUser])
return {
document,
loading
}
}
const MyComponent = () => {
const {document, loading} = useDocument()
console.log(loading) // changes to "loading" doesn't trigger rerender of this component
}
答案 0 :(得分:1)
此代码段中几乎没有错误,主要是因为变量unsubscribe
始终为undefined
,因为它甚至不在useEffect
的范围内。
这可能是一个有效的修复方法(仅通过查看代码就从未使用过firebase):
export function useDocument() {
const { auth, firestore } = useFirebase();
const [loading, setLoading] = useState(true);
const [document, setDocument] = useState();
useEffect(() => {
const watchDocument = async () => {
const unsubscribe = await params?.query.onSnapshot(
(doc) => {
setDocument(doc.data());
setLoading(false);
},
(err) => {
console.log(err);
setError(err.message);
}
);
};
let unsubscribe = null;
if (firestore && auth) {
unsubsribe = watchDocument();
}
return () => {
unsubscribe?.();
};
}, [firestore, auth]);
return {
document,
loading,
};
}
const MyComponent = () => {
const { document, loading } = useDocument();
console.log(loading);
};
答案 1 :(得分:0)
因此,问题在于依赖项auth?.currentUser
。 auth
本身会在状态更改时正确触发重新渲染。问题似乎是auth?.currentUser
中的更改无法检测到。
我的假设是,这是因为auth
被跟踪,并且即使auth
被firebase库更新了,对currentUser
的引用也没有改变。我最终将currentUser
移到了自己的useState
中,现在该组件可以正确地重新渲染了。