使用子功能组件调用setState()会导致无限循环

时间:2020-11-07 09:44:57

标签: javascript reactjs

我正在使用react-week-scheduler在页面上显示一周日历视图。该组件是基于类的父组件的功能子组件。我希望父组件管理日历上显示的事件的schedule状态,并将其作为道具传递给子组件。

我面临的问题是,每次我对TimeGrid进行调整(通过单击并拖动一个新的事件块)并触发我的handleGridChange函数将调整保存到schedule状态字段,由于setState导致子TimeGrid子组件更新,从而再次触发handleGridChange函数,使我进入无休止的循环。

如果我直接在子组件上处理TimeGrid状态,并使用schedule钩子对其进行更新,则useState组件可以正常工作,但是我的应用程序的其余部分没有进入schedule状态。我曾尝试将TimeGrid转换为基于类的组件,但是后来我遇到了setState的其他问题,因为我认为该组件并非旨在用于这种方式。

我对React钩子非常陌生/陌生,所以我觉得这可能会导致这个问题,甚至是全部问题。设置状态时,TimeGrid组件的设计与useEffect不断变化的方式可能也有关系,但是我不确定并且无法弄清楚。任何见解都将非常有帮助。

我的父组件看起来像这样:

import TimeGrid from './TimeGrid';

class ScheduleView extends Component {
  constructor(props) {
    super(props);
    this.state = {
      schedule: [], // initially empty
    };
  )

  handleGridChange(newSchedule) {
    this.setState({
      schedule: newSchedule,
    });
  }

  render() {
    return (
      <TimeGrid
        schedule={this.state.schedule}
        handleGridChange={this.handleGridChange.bind(this)}
      />
    );
  }
}

我的TimeGrid组件如下所示:

function TimeGrid(props) {
  // const [schedule, setSchedule] = useState([]); // <-- managing state with this works fine, but then I don't have access to it outside this component

  // oldHandleGridChange(newSchedule) {
  //   setSchedule(newSchedule);
  // }

  return (
    <TimeGridScheduler
      schedule={props.schedule}
      onChange={props.handleGridChange}
    />
  );
}

export default TimeGrid;

4 个答案:

答案 0 :(得分:1)

需要将其绑定到构造函数上,当函数绑定作为道具传递时,将创建一个新函数,道具将通过该函数表示更改再次触发渲染

import TimeGrid from './TimeGrid';

class ScheduleView extends Component {
  constructor(props) {
    super(props);
    this.state = {
      schedule: [], // initially empty
    };
    this.handleGridChange = this.handleGridChange.bind(this);
  )

  handleGridChange(newSchedule) {
    this.setState({
      schedule: newSchedule,
    });
  }

  render() {
    return (
      <TimeGrid
        schedule={this.state.schedule}
        handleGridChange={this.handleGridChange}
      />
    );
  }
}

答案 1 :(得分:0)

您只需触发一次onChange事件。或者简而言之,您可以使用粗箭头功能(=>)绑定该功能。

import TimeGrid from './TimeGrid';

class ScheduleView extends Component {
  constructor(props) {
    super(props);
    this.state = {
      schedule: [], // initially empty
    };
  )

  handleGridChange = (newSchedule) => {
    this.setState({
      schedule: newSchedule,
    });
  }

  render() {
    return (
      <TimeGrid
        schedule={this.state.schedule}
        handleGridChange={(e) => this.handleGridChange(e)} 
        /* or handleGridChange={ this.handleGridChange } */
      />
    );
  }
}

答案 2 :(得分:0)

主要是因为onChange函数在无限时间内触发,因此您需要在该处添加箭头运算符。

此链接可能对您有帮助 Prevent Infite loop

答案 3 :(得分:0)

使用它代替您的 handleGridChange 函数

<TimeGrid
        schedule={this.state.schedule}
        handleGridChange={(newSchedule) => this.setState({schedule: newSchedule})}
/>

可以肯定地工作。