useEffect 内的 setState 不会更新功能组件内的状态

时间:2021-03-13 12:24:51

标签: reactjs google-cloud-firestore

记录 firestore 查询的结果会产生我需要的所有数据,但是使用 setPosts 将其存储在“posts”变量中返回未定义。我确定我遗漏了一些明显的东西......

const Posts = () => {
      const [posts, setPosts] = useState();
    
      
      useEffect(() => {
        db.collection('posts')
        .get()
        .then((data) => {
          const results = data.docs.map((doc) => doc.data())
          console.log(results);
          // (8) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
          setPosts(results);
          console.log(posts);
          // undefined - why? 
        })
        .catch((error) => {
          console.error(error);
        });
      }, []);
    
      return ()};

2 个答案:

答案 0 :(得分:1)

当您在 console.log(posts) 中执行 useEffect() 时,此处的 posts 是指您为第一次渲染定义的值,即 undefined,因为您没有'不在 useState() 中指定默认值。

如果你把 console.log(posts) 放在 useEffect() 之外,你会看到它会记录 posts 两次,一次是第一次渲染,它仍然会注销 undefined,并且执行 setPosts() 后触发的第二个渲染中的另一个。

这样想,React 通过在每次更新状态时渲染来更新您的 UI。效果,与特定的渲染相关。在您的原始代码中,您的组件渲染了 2 次。

  1. 初始渲染,也将运行效果。
  2. 第二次渲染,在 setPosts(results) 更新状态后触发。此处不会运行任何效果,因为您将 [] 作为 useEffect() 钩子的依赖项,使其仅运行一次(在组件安装时)。

您在效果内部执行 console.log(posts),这意味着它是初始渲染的一部分。想一想,初始渲染中 posts 的值是多少?还是undefinedposts 的新值仅在第二次渲染中可用。

答案 1 :(得分:0)

删除了 console.log-s,现在一切正常。不知道为什么......我应该完全删除这个问题吗?

用于比较的工作代码:

const Posts = () => {
  const [posts, setPosts] = useState([]);

  
  useEffect(() => {
    db.collection('posts')
    .get()
    .then((data) => {
      const results = data.docs.map((doc) => doc.data())
      setPosts(results);
    })
    .catch((error) => {
      console.error(error);
    });
  }, []);
  
  return ()};