【问题标题】:Too many re-renders for component组件的重新渲染次数过多
【发布时间】:2021-07-30 22:53:23
【问题描述】:

我正在尝试调用一个组件,该组件会在单击通知时显示通知的详细信息。但是,我不断收到太多重新渲染的错误。

这是我的通知代码 该组件调用数据库获取通知列表,然后将第一个通知设置为默认点击通知。

const Notification = (hospital) => {
const [users, setUsers] = useState([]);
  const [search, setSearch] = useState(null);
  const [status, setStatus] = useState(null);

    const [notifDetails, setNotification] = useState();

useEffect(async () => {
    await axios
      .get("/notifications")
      .then((res) => {
        const result = res.data;
        setUsers(result);
        setNotification(result[0]);
      })
      .catch((err) => {
        console.error(err);
      });
  }, []);
    return(
      <div className="hospital-notif-container">
         {filteredList(users, status, search).map((details, index) => {
              for (var i = 0; i < details.receiver.length; i++) {
                if (
                  (details.receiver[i].id === hospital.PK ||
                    details.receiver[i].id === "others") &&
                  details.sender.id !== hospital.PK
                ) {
                  return (
                    <div
                      className="hospital-notif-row"
                      key={index}
                      onClick={() => setNotification(details)}
                    >
                      <div className="hospital-notif-row">
                          {details.name}
                      </div>
                    </div>
                  );
                }
              }
              return null;
            })}
          </div>
          <NotificationDetails details={notifDetails} /> 
   );
}

通知详情:

当点击通知中的通知时触发此功能。据说该错误来自此组件。

    const NotificationDetails = ({ details }) => {
  const [loading, setLoading] = useState(true);
useEffect(() => {
    if (Object.keys(details).length != 0) {
      setLoading(false);
    }
  }, [details]);
if (!loading) {
    return (
      <>
        <div className="hospital-details-container">
            <h2>{details.sender.name}</h2>
        </div>
     </>
    );
  } else {return (<div>Loading</div>);}
};

我应该怎么做才能限制重新渲染?我应该更改 useEffects 调用的第二个参数吗?还是我的组件中缺少某些内容?

我尝试从 NotificationDetails 调用 console.log,它显示它正在无限渲染我在 axios 中设置的数据,即结果 [0]。这是怎么回事?

【问题讨论】:

  • details.length != 0 然后details.sender.name? details 是对象还是数组?
  • 它是一个对象。我只是更改了长度来检查密钥。感谢您指出这一点!
  • 尝试在 if 语句 if (Object.keys(details).length != 0 &amp;&amp; loading === true) 中添加新参数,这将确保 setLoading(false) 将调用一次

标签: reactjs react-native react-hooks


【解决方案1】:

您的问题应该在NotificationDetails 渲染中。你应该这样写:

const NotificationDetails = ({ details }) => {
    const [loading, setLoading] = useState(true);
    useEffect(() => {
       if (details.length != 0) {
         setLoading(false);
       }
    }, [details]);

    return (
      <div>
       {loading && 
          <div className="hospital-details-container">
            <div className="hospital-details-header">
              <h2>{details.sender.name}</h2>
            </div>
          </div>
       }
       {!loading && 
          <div>
             <ReactBootStrap.Spinner animation="border" />
          </div>
       }
      </div>
    );
  }

在条件语句外加上return

编辑

现在我注意到您有一个异步useEffect,它是一种反模式。你应该这样修改你的useEffect

 useEffect(() => {
    (async () => {
      await axios
        .get("/notifications")
        .then((res) => {
           const result = res.data;
           setUsers(result);
           setNotification(result[0]);
        })
        .catch((err) => {
           console.error(err);
        });
    })()
  }, []);

【讨论】:

  • @AlsoJames 我忘了在条件语句之外加上div。我更新了我的答案。
  • @AlsoJames 也通过添加div 你仍然得到错误?
  • 这确实修复了意外的令牌错误。但我仍然收到太多重新渲染错误:(
  • 是的,因为现在我注意到你做了一个异步 useEffect。是反模式!我将用如何避免异步 useEffect 来更新我的答案
  • 非常感谢!我将尝试了解有关反模式的更多信息。
猜你喜欢
  • 1970-01-01
  • 2016-12-02
  • 1970-01-01
  • 2021-07-29
  • 1970-01-01
  • 2020-02-23
  • 2020-03-14
  • 2021-09-19
  • 1970-01-01
相关资源
最近更新 更多