【问题标题】:Why does this React component keep re rendering?为什么这个 React 组件一直在重新渲染?
【发布时间】:2020-10-25 22:28:02
【问题描述】:

如果用户在 firebase 中输入现有帖子的 ID,我会安装这个 Post 组件:

<Route path='/posts/:id' component={Post} />

但是,控制台记录此组件会无限期地发回日志,导致我的浏览器和页面上的操作非常缓慢。

这是 Post 组件的内容,我认为这与我在 useEffect 中设置状态的方式有关,但我不确定如何修复它。我试过 React.Memo 并没有用:

function Post(props: RouteComponentProps<PostParams>) {

  const [postData, setPostData] = useState({ title: '', body: '', author: '', time: 0, photoURL: '', likes: 0, dislikes: 0});
  const [existingComments, setExistingComments] = useState([])
  const [commentContent, setCommentContent] = useState('');
  const isMounted = useRef(false);
  const db = fb.firestore();
  const ref = db.doc(`posts/${props.match.params.id}`)

  useEffect(():any => {
    isMounted.current = true;
    ref.get().then((doc: any) => {
      if(doc.exists && isMounted.current) {
        setPostData(doc.data().content);
        setExistingComments(doc.data().comments ? doc.data().comments : [])
      }
    });
    return ()=> isMounted.current = false;
  });

  return ( 
  //... some html that displays the information I've got from firebase

提前感谢您的帮助:)

【问题讨论】:

  • useEffect之前添加[]

标签: javascript reactjs components react-hooks


【解决方案1】:

当您更新useEffect 中的状态时,由于状态更改,这会触发重新渲染,并且一旦组件更新,useEffect 会再次运行,这会更改状态,从而触发另一个渲染周期,因为这种模式您的组件一直在重新渲染。

您可以添加一个依赖数组来告诉 useEffect 仅在组件挂载时运行,也可以在发生更改时运行,如下所示:

function Post(props: RouteComponentProps<PostParams>) {

    const [postData, setPostData] = useState({ title: '', body: '', author: '', time: 0, photoURL: '', likes: 0, dislikes: 0 });
    const [existingComments, setExistingComments] = useState([])
    const [commentContent, setCommentContent] = useState('');

    useEffect((): any => {
        const db = fb.firestore();
        const ref = db.doc(`posts/${props.match.params.id}`)
        ref.get().then((doc: any) => {
            if (doc.exists && isMounted.current) {
                setPostData(doc.data().content);
                setExistingComments(doc.data().comments ? doc.data().comments : [])
            }
        });
        return () => { };
    }, [setPostData, setExistingComments]);
    // setPostData, setExistingComments won't get a new reference for every render so they won't cause useEffect to run
    return (<></>);
}

【讨论】:

  • 谢谢,就是这样。为了将来参考,我还必须将props.match.params.id 添加到依赖数组中。
  • 是的,您需要添加在组件内部定义并在useEffect 中使用的所有变量以避免过时的值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-12
  • 2020-09-15
  • 2020-08-29
  • 2021-10-21
  • 2023-02-20
  • 2020-08-14
  • 1970-01-01
相关资源
最近更新 更多