Реакция: как использовать setState и визуализировать компонент при изменении реквизита - PullRequest
1 голос
/ 02 мая 2019

Это приложение должно фильтровать слова по конкретному входу. Я хочу вызвать функцию с setState() при рендеринге компонента, и технически он работает, но в консоли есть предупреждение.

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

Полагаю, это потому, что я вызываю функцию в функции рендеринга, чего не следует делать, но что мне делать вместо этого?

class UsersList extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      allUsers: ["Michał", "Ania", "Kasia", "Tomek", "Hubert", "Jan", "Martyna", "Rafał", "Bartłomiej"],
      filteredUsers: [],
      input: null
    }
  }

  filter() {
    if (this.state.input !== this.props.inputValue) {
      const filtered = this.state.allUsers.filter(user => user.toLowerCase().includes(this.props.inputValue));
      this.setState({
        filteredUsers: filtered.map(user => <li key={user}>{user}</li>),
        input: this.props.inputValue
      })
    }

    return this.state.filteredUsers;
  }

  render() {
    this.filter()
    return (
      <ul>
        {this.state.filteredUsers}
      </ul>
    )
  }
}

class App extends React.Component {

  constructor() {
    super();

    this.state = {input: ""};
    this.handleInput = this.handleInput.bind(this);
  }

  handleInput(e) {
    this.setState({input: e.target.value})
  }

  render() {
    return (
      <div>
        <input onChange={this.handleInput} type="search"/>
        <UsersList inputValue={this.state.input} />
      </div>
    );
  }
}

Ответы [ 2 ]

1 голос
/ 02 мая 2019

Проблема здесь вызвана изменениями, вносимыми в состояние вашего компонента во время рендеринга.

Следует избегать установки состояния компонента непосредственно во время функции render() компонентов (это происходит при вызове filter() во времяrender() функция вашего компонента).

Вместо этого рассмотрите возможность обновления state вашего компонента только по мере необходимости (то есть, когда изменяется inputValue опора).Рекомендуемый способ обновления state при изменении значений prop - через ловушку жизненного цикла компонента getDerivedStateFromProps().

Вот пример того, как вы можете использовать этот хук для вашего компонента:

class UsersList extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            allUsers: ["Michał", "Ania", "Kasia", "Tomek", 
                       "Hubert", "Jan", "Martyna", "Rafał",
                       "Bartłomiej"],
            filteredUsers: [],
            input: null
        }
    }

    /* Add this life cycle hook, it replaces filter(). Props are updated/incoming 
       props, state is current state of component instance */
    static getDerivedStateFromProps(props, state) {

        // The condition for prop changes that trigger an update
        if(state.input !== props.inputValue) {

            const filtered = state.allUsers.filter(user => user.toLowerCase().includes(props.inputValue));

            /* Return the new state object seeing props triggered an update */
            return {
                allUsers: state.allUsers
                filteredUsers: filtered.map(user => <li key={user}>{user}</li>),
                input: props.inputValue
            }
        }

        /* No update needed */
        return null;
    }

    render() {

        return (<ul>{this.state.filteredUsers}</ul>)
    }
}

Надеюсь, это поможет

0 голосов
/ 02 мая 2019

Ошибка появляется, поскольку это может создать бесконечный цикл внутри компонента. Поскольку render метод выполняется всякий раз, когда состояние обновляется, а ваша функция this.filter выполняет обновление состояния. Теперь, когда состояние обновляется, ваш метод рендеринга снова вызывает функцию.

Лучший способ сделать это - lifecycle methods или сохранить использование в App и сделать UserList немым компонентом, всегда передавая список отфильтрованных пользователей для его отображения.

...