如何处理由于从 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 多次渲染ServiceEstabelecimentoserviceList 使用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 检索到的标记在我的地图上?

如何从 Firestore 中检索浮动?

如何在 UIPickerView 中加载从 Firestore 检索到的数据?

如何从firestore检索图像到recyclerview

Firestore 如何存储对文档的引用/如何检索它?

如何从 Cloud Firestore 上的对象中检索值?迅速