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

时间:2020-10-24 03:40:39

标签: javascript reactjs react-hooks fullcalendar

我正在使用fullcalendar库来获取“要做”笔记的一小部分,只是为了学习React js(我是新来的)。当我从Firebase上的实时数据库中获取数据时,我尝试将事件名称(evento)和日期(fecha)显示到日历中,但是当我使用setName()放置数据并将其保存到arrey中时name = [],然后通过我出现了一个错误,例如重新渲染,我不知道该如何解决....如果有人可以帮助我,那将很棒! (对不起,我的英语不好) 谢谢

这是错误和代码: enter image description here

    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 个答案:

答案 0 :(得分:1)

您要使用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()中运行代码并重新渲染。

更多内容可以阅读here

顺便说一句,还有一个小小的优化可以应用,就是使用局部变量来存储过程中的值。然后只调用一次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'));

答案 1 :(得分:0)

您有2个问题:

  1. firebase在react组件内部创建侦听器。
  2. import bs4 as bs import urllib.request sauce = urllib.request.urlopen('https://drafty.cs.brown.edu/csprofessors').read() soup = bs.BeautifulSoup(sauce, 'lxml') table = soup.find('template', attrs={"id":"table-data"}) for tr in table.find_all('tr'): td = tr.find_all('td') row = [i.text for i in td] print(row) 内调用setName;

我会告诉你循环在哪里。

  1. 组件已呈现;
  2. 组件创建状态Array.prototype.forEach;
  3. 组件调用[name, setName];
  4. 回调从Firebase获取数据并通过forEach通过键进行迭代;
  5. 在forEach的第一次迭代中,您调用firebase.database().ref().on('value', callback);
  6. setName呼叫重新呈现;
  7. 转到setName步骤;

解决方案:

3