Как избежать бесконечного цикла повторного рендеринга, когда вам нужно установить состояние в Render ()?

#reactjs #antd

#reactjs #antd

Вопрос:

У меня есть компонент родительского класса с состояниями (StartDate и EndDate), которые устанавливаются дочерним компонентом. В дочернем компоненте есть компоненты выбора даты. Смотрите приведенный ниже код как для родительского, так и для дочернего компонентов:

Родительский

 import React, { Component } from 'react';
import Child from './child-component'

class Parent extends Component {

state = {
  startDate: null,
  endDate: null,
}

startDSelected = (startD) => {
  this.setState({
    startDate: startD,
  })
}

endDSelected = (endD) => {
  this.setState({
    endDate: endD,
  })
}

  render() {
    return (
      <div>
        <Child selectedStartDate={startDSelected} selectedEndDate={endDSelected}>
      </div>
    );
  }

}

export default Parent;
  

Дочерний элемент

 import React, { Component } from 'react'

import { DatePicker } from "antd"

class Child extends Component {

  constructor(props) {
    super(props)
    this.state = {
      startValue: null,
      endValue: null,
      endOpen: false,
    }
  }

  onStartChange = (value) => {
    this.setState({
      startValue: value
    })
  }

  onEndChange = (value) => {
    this.setState({
      endValue: value
    })
  }

  handleStartOpenChange = (open) => {
    if (!open) {
      this.setState({ endOpen: true })
    }
  }

  handleEndOpenChange = (open) => {
    this.setState({ endOpen: open })
  }

  datesGetChanged = () => {
    const { startValue, endValue } = this.state
    this.props.selectedStartDate(startValue)
    this.props.selectedEndDate(endValue)
  }

  render() {
    const { startValue, endValue, endOpen } = this.state
    this.datesGetChanged()
    return (
      <div style={{ display: `inline-block` }}>
        <DatePicker
          format="YYYY-MM-DD"
          value={startValue}
          placeholder="Start"
          onChange={this.onStartChange}
          onOpenChange={this.handleStartOpenChange}
          />
          <DatePicker
          format="YYYY-MM-DD"
          value={endValue}
          placeholder="End"
          onChange={this.onEndChange}
          open={endOpen}
          onOpenChange={this.handleEndOpenChange}
          />
      </div>
    )
  }

}

export default Child;
  

Поэтому каждый раз, когда мне нужно устанавливать родительские состояния при изменении новых значений даты в дочернем компоненте, я получаю бесконечный цикл повторного рендеринга. Как это предотвратить?

Комментарии:

1. Вы не должны вызывать setState непосредственно при рендеринге. Вместо этого вы можете поднять состояние до родительского и передать его в качестве реквизита.

2. проблема в том, что вам не нужно устанавливать состояние в функции рендеринга. Функция рендеринга должна быть чистой функцией, без каких-либо изменений состояния. Вы должны поднять свое состояние

3. Спасибо, ребята!! Да, мне пришлось поднимать состояния, и это сработало потрясающе!

Ответ №1:

Подводя итог нескольким замечаниям, которые я видел, вы должны удалить this.datesGetChanged() из своей render функции. Если состояние родительского элемента должно обновляться при изменении состояния дочернего элемента, затем обновите состояние родительского элемента при изменении состояния дочернего элемента. В вашем коде это будут onChange функции ваших средств выбора даты.

render это то, что React выполняет по своему собственному расписанию, и вызов функции изменения состояния внутри нее является рецептом для бесконечных циклов, которые вы описываете.

Чтобы процитировать документы React:

Функция render() должна быть чистой, что означает, что она не изменяет состояние компонента, возвращает один и тот же результат при каждом вызове и не взаимодействует напрямую с браузером.

render docs

Ответ №2:

 componentDidUpdate(prevProps) {

this.datesGetChanged()

}