如何处理由于从 Firestore DB 检索而多次运行的 UseEffect?
Posted
技术标签:
【中文标题】如何处理由于从 Firestore DB 检索而多次运行的 UseEffect?【英文标题】:How to deal with UseEffect running multiple times due to retrieval from Firestore DB? 【发布时间】:2020-10-28 02:02:38 【问题描述】:编辑:几乎改变了这个问题的全部内容
我正在构建一个预订应用程序。正在发生大量的重新渲染,根据@jpmarks 的建议,我试图找出哪个 useEffect 可能是罪魁祸首,并认为可能是下面的代码,它运行了 24 次。
我还将所有相关的组件和控制台警告上传到this repo,假设其他组件可能会影响它。
useEffect(
() =>
console.log('useEffect ServicEstabelecimento ran') //runs 24 times
async function getOfferedServicesFromDB()
const approved = await approvedBusinessService.doc(businessId)
const snapshotApproved = await approved.get()
if (snapshotApproved.exists && snapshotApproved.data().offeredServices)
setOfferedServices(Object.values(snapshotApproved.data().offeredServices))
else
const pending = await businessPendingApprovalService.doc(businessId)
const snapshotPending = await pending.get()
if (snapshotPending.exists && snapshotPending.data().offeredServices)
setOfferedServices(Object.values(snapshotPending.data().offeredServices))
return
getOfferedServicesFromDB()
,
[
/* businessId, setOfferedServices */
],
)
//React Hook useEffect has missing dependencies:
//'businessId' and 'setOfferedServices'.
//Either include them or remove the dependency array
//Tried adding them separately or both, nothing changes
我在这里要做的是查看企业提供哪些服务,并从数据库中获取该信息。无论业务是否已被接受,处理方式都会发生变化。
【问题讨论】:
您可以从 useEffect 依赖数组中删除“allBookings”,因为它没有在效果内使用。这可能是原因。由于您的效果实际上并未直接更新任何组件状态,因此除非 businessRef 方法导致组件以其他方式呈现,否则它不会导致渲染。 @jpmarks 我试过了,但没用,重新渲染继续进行 This line 被数组中的每个服务调用,从而为每个挂载的ServiceEstabelecimento
重复效果
【参考方案1】:
我查看了您的源代码,看起来该组件不对不必要的渲染负责。我建议按照您的编辑器告诉您的那样修复依赖关系,看看这是否修复了某些问题。 我坚信您的上下文会在您的一个效果中更新,从而导致上下文重新渲染组件。 要从上下文中找出导致渲染的状态,您可以对它们中的每一个使用 useEffect 来检查。
const theme, userObject, dateForRenderingTimeGrid = useContext(Context);
useEffect(() =>
console.log("Theme updated");
, [theme]);
useEffect(() =>
console.log("UserObject updated");
, [userObject]);
useEffect(() =>
console.log("DateForRenderingTimeGrid updated");
, [dateForRenderingTimeGrid ]);
让我知道你在看什么。如果这些都没有真正触发效果,但您仍然看到渲染,那么您可以确定它发生在您的组件中
【讨论】:
我已经尝试遵循这个,发现问题可能出在一个完全不同的组件上!谢谢。我已经更新了问题和 repo。【参考方案2】:一种可能性是在Options.js
中,您使用serviceList.map
多次渲染ServiceEstabelecimento
。 serviceList
使用serviceListService.collection().onSnapshot
回调在 useEffect 中设置。有了这个,你的 useEffect 自然会被调用 24 次(如果 serviceList 在快照回调中得到 24 的值)
另一种可能性是您正在使用三元组渲染 ServiceEstabelecimento
。这将根据estabelecimento
的值卸载/重新安装组件。
const ContextOptionsEstabelecimento = React.createContext()
export const Options = () =>
const estabelecimento, theme, offeredServices = useContext(Context)
const [isConfiguring, setIsConfiguring] = useState(false)
const [serviceList, setServiceList] = useState([])
useEffect(() =>
const unsubscribeServices = serviceListService.collection().onSnapshot(snapshot =>
const services = snapshot.docs.map(collectIdsAndDocs)
setServiceList(services) //<-----see here
)
return () =>
unsubscribeServices()
, [])
const serviceElements = serviceList.map(service => //<-----see here
!estabelecimento ? ( //<-----see here
<Service
key=service.id
id=service.id
name=service.name
type=service.type
title=service.info
duration=service.duration
/>
) : ( //<-----see here
<ContextOptionsEstabelecimento.Provider value= isConfiguring key=service.id>
<ServiceEstabelecimento
key=service.id
id=service.id
name=service.name
type=service.type
title=service.info
duration=service.duration
/>
</ContextOptionsEstabelecimento.Provider>
),
)
return (
...
检查以上内容,看看你的进展如何。还分享完整的 repo(如果可能的话)以进一步调试。
我还看到一些架构问题,因为我看到大型对象与多个上下文一起使用。这将有组件不必要地重新渲染的风险。我假设您正在处理此类事情。
【讨论】:
以上是关于如何处理由于从 Firestore DB 检索而多次运行的 UseEffect?的主要内容,如果未能解决你的问题,请参考以下文章
如何在不重新加载页面的情况下更新从 firestore 检索到的标记在我的地图上?