首页 > 解决方案 > useEffect 挂钩未正确设置状态对象

问题描述

好的,我真的无法弄清楚为什么会这样。我在不同的组件上做同样的事情,有时它有效,有时它不。我使用 useEffect 挂钩从我的 firebase 存储中获取对象。如控制台所示,我正确获取了对象,但实际上我无法访问任何嵌套值。

代码:

const ReviewComponent = (props) => {
  const [open, setOpen] = useState(false)
  const [campaigns, setCampaigns] = useState([])
  const [currentCampaign, setCurrentCampaign] = useState([])

//First useEffect hook used for something else in the code
  const tempDoc = []
      useEffect(() => {
        var docRef = db.collection("campaigns");
        docRef.get().then(function(querySnapshot) {
          querySnapshot.forEach(function(doc) {
            tempDoc.push({ id: doc.id, ...doc.data() })
              // doc.data() is never undefined for query doc snapshots
              setCampaigns(tempDoc)
          });
      })
      .catch(function(error) {
          console.log("Error getting documents: ", error);
      });
      },[]);


//Second use effect hook (THIS IS THE ONE CAUSING ISSUES)
      useEffect(() => {
        const docRef = db.collection("campaigns").doc(slug);
    
        docRef.get().then(function(doc) {
            if (doc.exists) {
                console.log("Document data:", doc.data());
                setCurrentCampaign(doc.data()) 
            } else {
                // doc.data() will be undefined in this case
                console.log("No such document!");
            }
        }).catch(function(error) {
            console.log("Error getting document:", error);
      });
    },[]);


  const handleOpen = () => {
    setOpen(true)
  };

  const handleClose = () => {
    setOpen(false);
  };

  if(currentCampaign[0]) { // Or if(campaign[0])

    console.log(currentCampaign) //this never gets logged 
  }

  return(
    <Typography>
    {currentCampaign.reviews[0].text} // TypeError: Cannot read property 'text' of undefined, if I do currentCampaign.reviews -> TypeError: Cannot read property 'reviews' of undefined
   </Typography>
)

文本

如您所见,上图显示了从 useEffect 挂钩中记录的对象。我尝试通过检查 currentCampaign[0] 是否存在来记录它。它永远不存在。如果我执行 currentCampaign.body 或任何其他顶级元素,它在我的 return 语句中工作正常。如果我做任何嵌套的事情,例如 currentCampaign.images[0].url -> ERROR :

我可以访问所有顶级属性,例如 body、campaignPolicy 等,但如果我这样做了

TypeError:无法读取未定义的属性“秒”

如果我做campaign.startDate.seconds 我得到同样的错误:

TypeError:无法读取未定义的属性“秒”

标签: reactjsfirebasegoogle-cloud-firestoreuse-effect

解决方案


if(currentCampaign[0]) { // Or if(campaign[0])
    console.log(currentCampaign) //this never gets logged 
}

您不能在ReviewComponent组件的根级别请求状态值,这意味着状态定义的同一级别。这在组件渲染时最初调用一次,因此 currentCampaign 始终为空。

您应该在useEffect添加状态依赖项的情况下使用它。

useEffect(() => {
  if(currentCampaign[0]) {
    console.log(currentCampaign)
  }
}, [currentCampaign]);

return(
    <Typography>
       {currentCampaign.reviews[0].text}
   </Typography>

关于这个错误,currentCampaign 最初是空数组,所以在这个组件第一次渲染时,currentCampaign.reviews 是未定义的。因此currentCampaign.reviews[0].text将是错误。

您应该始终检查currentCampaign它是否未定义。

仅供参考,currentCampaign是您的状态定义中的数组,因此请尝试更正语法以请求currentCampaign变量。


推荐阅读