尽管状态发生了变化,但自定义挂钩不会触发组件重新应答



上下文:我有一个自定义挂钩,用于获取firestore文档。它监视文档的更改,然后返回它和加载状态。我在另一个组件中使用这个钩子。

问题:对钩子返回的状态值(loadingdocument(的更改不会触发组件使用钩子重新发送并查看更新的值。

我的发现:其他自定义挂钩可以工作并触发渲染,所以useDocument挂钩一定有问题。如果另一个钩子触发了一个重新应答器,那么loading最终才会更新。loadingdocument的值确实在钩子内按预期更新,但组件的重新发布器仍然从未被触发。

重要说明: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中,现在组件正确地重新发布了。

最新更新