为什么这个React组件会保持重新渲染?

时间:2020-07-05 19:05:42

标签: javascript reactjs components react-hooks

如果用户输入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

在此先感谢您的帮助:)

1 个答案:

答案 0 :(得分:0)

当您在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 (<></>);
}