上下文:我有一个自定义挂钩,用于获取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
}
这个片段中几乎没有错误,主要是变量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);
};
所以问题是依赖关系auth?.currentUser
。CCD_ 14本身在状态改变时适当地触发重新渲染。问题似乎是CCD_ 15的变化是无法检测到的。
我的假设是,这是因为auth
是被跟踪的内容,并且即使currentUser
被firebase库更新,对auth
的引用也不会改变。我最终将currentUser
移动到它自己的useState
中,现在组件正确地重新发布了。