为了账号安全,请及时绑定邮箱和手机立即绑定

React 的 useState 问题,太多的重新渲染

React 的 useState 问题,太多的重新渲染

回首忆惘然 2023-06-09 10:59:16
我正在将 fullcalendar 库用于一个小的&ldquo;待办事项&rdquo;笔记项目,只是为了学习 React js(我是新手)。当我从 firebase 上的实时数据库中获取数据时,我尝试在日历中显示事件名称 (evento) 和日期 (fecha),但是当我使用 setName() 来放置数据并将其保存到数组中时name=[],然后通过我重新渲染这样的错误,我不知道如何修复它....如果有人能帮助我,那就太好了!(对不起我的英语不好)谢谢这是错误和代码:    const [date, SetFecha] = useContext(Contexto)    const [name, setName] = useState([])    firebase.database().ref().on('value', (snapshot) => {        let obj = snapshot.val()        Object.values(obj.Notas).forEach(e => {            setName([...name, { title: e.evento, date: e.fecha }])        });    })    const DateClick = (arg) => {        SetFecha(arg.dateStr)        }    return (        <FullCalendar            plugins={[dayGridPlugin, listPlugin, interactionPlugin]}            initialView="dayGridMonth"            dateClick={DateClick}            events={name}         />    )解决方案 useEffect(() => {        firebase.database().ref().on('value', (snapshot) => {            let obj = snapshot.val()            let arr = []            Object.values(obj.Notas).forEach(e => {                arr.push({ title: e.evento, date: e.fecha })            });            setName(arr)        })    }, []);
查看完整描述

2 回答

?
慕田峪4524236

TA贡献1875条经验 获得超5个赞

你想使用useEffect钩子。尝试类似的东西:


  useEffect(() => {

    firebase.database().ref().on('value', (snapshot) => {

      const obj = snapshot.val();

      const arrData = [];

      Object.values(obj.Notas).forEach(e => 

        arrData.push({ title: e.evento, date: e.fecha }));

      setName(arrData);

    });

  }, firebase.database().ref().on('value'));

您在上面的代码中显示的问题是每次调用时setName()都会重新渲染组件(这是 React 返回的一个特殊函数,用于更改组件状态并重新渲染)。当它重新渲染时,setName()再次调用,从而导致重新渲染中的无限循环。


useEffect()不会在重新渲染时运行,而是仅在检测到数据已更改时运行。在这种情况下,它会检查是否firebase.database().ref().on('value')已更改,如果是,则运行代码useEffect()并重新渲染。


顺便说一句,可以应用一个小的优化是使用局部变量来存储过程中的值。然后setName()只调用一次。因为如前所述,每次调用这个特殊函数,都可能导致重新渲染。所以你只想在完成所有中间过程后调用它一次。或者更好的是,以函数式风格进行:


  useEffect(() => {

    firebase.database().ref().on('value', (snapshot) => {

      setName(Object.values(snapshot.val().Notas).map(e => 

        { title: e.evento, date: e.fecha }));

    });

  }, firebase.database().ref().on('value'));


查看完整回答
反对 回复 2023-06-09
?
拉风的咖菲猫

TA贡献1995条经验 获得超2个赞

你有两个问题:

  1. firebase 在反应组件中创建监听器。

  2. 在里面调用 setName Array.prototype.forEach

我会告诉你循环在哪里。

  1. 组件被渲染;

  2. 组件创建状态[name, setName]

  3. 组件调用firebase.database().ref().on('value', callback)

  4. Callback从firebase获取数据,通过forEach按键进行迭代;

  5. 在您调用 forEach 的第一次迭代中setName

  6. setName调用重新渲染;

  7. 走到3台阶;

解决方案:

function OwnComponent(props) {

  const [date, setFecha] = useContext(Contexto);

  const [name, setName] = useState([]);

    

  const dateClick = React.useCallback((arg) => {

    setFecha(arg.dateStr);

  }, [setFecha]);

    

  React.useEffect(() => {

    const unsubscribe = firebase.database().ref(/* you can pass 'Notas' 

 here */).on('value', (snapshot) => {

      setName(Object.values(snapshot.val().Notas/* you can remove .Notas here */).map(

        ({ evento: title, fecha: date }) => ({ title, date })

      ));

    });


    return () => {

      unsubscribe();

    };

  }, []);

    

  return (

    <FullCalendar

      plugins={[dayGridPlugin, listPlugin, interactionPlugin]}

      initialView="dayGridMonth"

      dateClick={dateClick}

      events={name} 

    />

  );

}


查看完整回答
反对 回复 2023-06-09
  • 2 回答
  • 0 关注
  • 230 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信