如何解决自定义钩子不会触发组件重新渲染,尽管状态发生了变化
上下文:我有一个自定义钩子,用于获取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
。 auth
本身会在状态更改时正确触发重新渲染。问题似乎是auth?.currentUser
中的更改无法检测到。
我的假设是,这是因为auth
被跟踪,并且即使auth
被firebase库更新了,对currentUser
的引用也没有改变。我最终将currentUser
移到了自己的useState
中,现在该组件可以正确地重新渲染了。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。