【问题标题】:How to deal with UseEffect running multiple times due to retrieval from Firestore DB?如何处理由于从 Firestore DB 检索而多次运行的 UseEffect?
【发布时间】: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重复效果

标签: javascript reactjs firebase google-cloud-firestore use-effect


【解决方案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(如果可能的话)以进一步调试。

我还看到一些架构问题,因为我看到大型对象与多个上下文一起使用。这将有组件不必要地重新渲染的风险。我假设您正在处理此类事情。

【讨论】:

    猜你喜欢
    • 2023-01-27
    • 1970-01-01
    • 1970-01-01
    • 2019-12-25
    • 2020-09-03
    • 1970-01-01
    • 2022-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多