【问题标题】:using setState getting Too many re-renders使用 setState 获得太多的重新渲染
【发布时间】:2021-07-09 23:24:01
【问题描述】:

我有一个用于选择已验证、未验证和所有事件的下拉菜单 我目前正在实施已验证的事件部分 当我使用 setEvents 更改事件的值时,我遇到了太多渲染错误

Event.js

import EventList from '../components/EventList'
import React, { Component ,useEffect,useState} from 'react'
import Selector from '../components/Selector';
import Navbar from '../../shared/components/navigation/Navbar';

// export class Event extends Component {

// constructor(props) {
//     super(props);
//     this.state = {
//         eventType:'ALLEVENTS',
//         events:{},
//     };
//     this.handelChange = this.handelChange.bind(this)
// }
//     handelChange = (e)=>{
//         this.setState({eventType:e.target.value})
//     }

//     filteredEvents=[]

//     render() {

//             const sendRequest = async () => {
//               try {
//                 const response = await fetch('http://localhost:5000/api/events');
          
//                 const responseData = await response.json();
//                 this.setState({events:responseData})

//                 if (!response.ok) {
//                   console.log("error")
//                 }
          
//               } catch (err) {
//                 console.log(err);
//               }
//             };

//             sendRequest();
        
//     const currentEventType = this.state.eventType;


//     if(currentEventType === 'VERIFIED'){
//         this.filteredEvents = this.state.events.filter(event =>event.verified === true);
//     }
//     else if(currentEventType === 'UNVERIFIED'){
//         this.filteredEvents = this.state.events.filter(event =>event.verified === false);
//     }
//     else{
//         this.filteredEvents = this.state.events;
//         console.log(this.state.events)
//         console.log("hhiiiiiiiiiiii")
//     }

//     return (
//         <React.Fragment>
//             <Navbar/>
//             <Selector handelChange={this.handelChange}/>
//             <div>
//             <EventList events={this.state.events} />
//             </div>
//         </React.Fragment>
//         )
//     }
// }

// export default Event

// import React from 'react'

const Event = () => {

    const [eventType,seteventType] = useState('ALLEVENTS');
    const [filteredEvents,setfilteredEvents] = useState();
    const [events,setevents] = useState([]);
    const [isLoading,setisLoading] = useState(true);

    const handelChange = (e)=>{
        console.log(e.target.value)
        seteventType(e.target.value)
    }

    useEffect(() => {
    const sendRequest = async () => {
        try {
          const response = await fetch('http://localhost:5000/api/events');
    
          const responseData = await response.json();
          
          console.log(responseData)
          console.log("responseData")

          if (!response.ok) {
            console.log("error")
          }
        console.log(responseData)
        setevents(responseData)
        setisLoading(false)
    
        } catch (err) {
          console.log("errrrrrroooooooorrrrrrr");
          console.log(err);
        }
      };
      sendRequest();
    },[]);
  
    // const currentEventType = this.state.eventType;
    if(isLoading === false){
        if(eventType === 'VERIFIED'){
            console.log("verified")
            console.log(events['events'])
            setevents(Array.isArray(events['events']) ? events['events'].filter(event =>event.verified === true) : []);
        }
}
    else if(eventType === 'UNVERIFIED'){
        events.filter(event =>event.verified === false);
    }
    else{
        console.log(events)
        // setfilteredEvents(events);
    }


    return (
        <React.Fragment>
            <Navbar/>
           
            <Selector  handelChange={handelChange}/>
            <div>
                {!isLoading &&
            <EventList events={events} />}
            </div>
        </React.Fragment>
    )
}

export default Event

这部分代码负责处理状态的设置,我正在检查是否从服务器获取数据然后更改isLoading的值

 if(isLoading === false){
        if(eventType === 'VERIFIED'){
            console.log("verified")
            console.log(events['events'])
            setevents(Array.isArray(events['events']) ? events['events'].filter(event =>event.verified === true) : []);
        }
}

沙盒链接 https://codesandbox.io/s/jovial-merkle-2bprs?file=/src/user/pages/Auth.js

【问题讨论】:

  • 为什么在useEffect 中有events 作为依赖项?这就是导致无限重新渲染的原因(您在其中调用setevents),但我看不到您在函数中使用events 的任何地方?
  • 哎呀我只是在测试,但删除后我得到了同样的错误
  • 谢谢,我现在看到了另一个问题:从if(isLoading === false) 开始的整个块实际上没有任何意义,如果每次都执行调用setevents 的部分,则会导致无限渲染。您不应该有任何这样的代码在函数组件的主体内设置状态 - 每次函数呈现时都会调用该函数!我不明白你要做什么,但如果这段代码有任何意义,那么它可能应该在 useEffect 函数中。
  • 我添加了if(isLoading === false),以确保在根据验证状态过滤之前加载数据

标签: javascript reactjs fetch state react-component


【解决方案1】:

您已将events 添加为useEffect 的依赖项,并且您在useEffect 中调用setevents。这会导致无限循环的渲染,因为每次setevents 设置您的eventuseEffect 都会被触发并再次调用setevents

【讨论】:

  • 是的,我删除了它,但仍然遇到同样的错误
  • 你也有 setevents 作为一个不需要存在的依赖项。现在,只需尝试为您的依赖项传递一个空列表 []
  • 尝试将您的代码放在沙箱中,以便我们帮助您调试
  • 但我使用的是来自本地服务器的数据,我认为这会导致沙箱出现问题
猜你喜欢
  • 2021-11-21
  • 1970-01-01
  • 1970-01-01
  • 2020-04-23
  • 2020-11-27
  • 1970-01-01
  • 1970-01-01
  • 2016-09-09
  • 2020-08-15
相关资源
最近更新 更多