Компоненты на основе класса React: бесконечный цикл

#reactjs #components

#reactjs #Компоненты

Вопрос:

У меня проблема с обновлением состояния в компоненте. Я создаю приложение todo с компонентом на основе классов. В этом приложении у меня есть фильтр, поэтому вы можете выбрать отображение завершенной задачи, незавершенных задач или всех задач. Итак, у меня есть массив с задачами. А затем я создал еще один массив: filteredItems, где я фильтрую задачи в соответствии с тем, какой вариант был выбран.

Я делаю это в componentDidUpdate, но я всегда получаю бесконечный цикл. Спасибо за помощь.

Вот код:

 class TodoApp extends React.Component {
  constructor(props) {
    super(props);
    this.state = { items: [], text: "", option: "all", filteredItems: [] };
  }

  componentDidUpdate() {
    switch (this.state.option) {
      case "completed":
        const completedItems = this.state.items.filter(
          (item) => item.completed
        );
        this.setState(() => ({
          filteredItems: completedItems,
        }));
        break;
      case "uncompleted":
        const uncompletedItems = this.state.items.filter(
          (item) => item.completed === false
        );
        this.setState(() => ({
          filteredItems: uncompletedItems,
        }));
        break;
      default:
        this.setState(() => ({
          filteredItems: this.state.items,
        }));
    }
  }

  render() {
    return (
      <div className="app-container">
        <h3>TODO</h3>
        <TodoForm
          items={this.state.items}
          handleChange={this.handleChange}
          handleSubmit={this.handleSubmit}
          handleOption={this.handleOption}
          value={this.state.text}
        />
        <TodoList
          items={this.state.items}
          deleteTodo={this.deleteTodo}
          softDeleteTodo={this.softDeleteTodo}
        />
      </div>
    );
  }

  handleChange = (e) => {
    this.setState({ text: e.target.value });
  };

  handleSubmit = (e) => {
    e.preventDefault();
    if (!this.state.text.length) {
      return;
    }
    const newItem = {
      text: this.state.text,
      id: Date.now(),
      completed: false,
    };
    this.setState((state) => ({
      items: [...state.items, newItem],
      text: "",
    }));
  };

  //Function delete todo
  deleteTodo = (item) => {
    const updateItems = this.state.items.filter(
      (element) => element.id !== item.id
    );

    this.setState(() => ({
      items: updateItems,
    }));
  };

  //Function softdeleteTodo
  softDeleteTodo = (item) => {
    const completedItems = this.state.items.map((element) => {
      if (element.id === item.id) {
        return { ...element, completed: !element.completed };
      }
      return element;
    });

    this.setState(() => ({
      items: completedItems,
    }));
  };

  //Set state according to which option was selected
  handleOption = (event) => {
    this.setState({ option: event.target.value });
  };
}

export default TodoApp;
 

Компонент TodoForm:

 import TodoInput from "./TodoInput";

export default function TodoForm({
  items,
  handleChange,
  handleSubmit,
  value,
  handleOption,
}) {
  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="new-todo">What needs to be done?</label>
      <TodoInput id="new-todo" handleChange={handleChange} value={value} />

      <button>{`Add #${items.length   1}`}</button>

      <select onChange={handleOption}>
        <option value="all">All</option>
        <option value="completed">Completed</option>
        <option value="uncompleted">Uncompleted</option>
      </select>
    </form>
  );
}
 

Ответ №1:

Проблема
Вы обновляете состояние в componentDidUpdate() .

После обновления состояния он повторно отображает компонент TodoApp.
По мере повторного отображения componentDidUpdate() компонента TodoApp запустите снова и обновите состояние.
Этот цикл повторяется снова и снова, и вы получаете бесконечный цикл.

Прежде всего избавьтесь от componentDidUpdate() .

1.
Решение № 1 Создайте функцию в компоненте TodoApp, которая принимает один аргумент и обновляет ваше состояние в компоненте TodoApp.
2. Теперь передайте эту функцию в качестве реквизита в вашем комментарии к TodoForm.
3. Теперь вы можете получить доступ к этой функции в вашем компоненте TodoForm в качестве реквизита, и вам нужно прикрепить onClick() событие к опции вашего элемента select и передать его значение параметра функции, полученной из TodoApp в качестве реквизита, и обновить свое состояние в компоненте TodoApp.

Решение № 2
Не сохраняйте свое option состояние в своем this.state . Вместо этого вы можете сохранить свое option состояние в библиотеке управления состояниями, например redux , и вам нужно отправить действие, чтобы изменить свое состояние.
Какой стажер отрисовывает ваш компонент один раз.
В опции выбора элемента вашего компонента TodoForm вы должны прикрепить onClick() событие и отправить из него действие.

Здесь Вы можете узнать больше
Нажмите здесь, чтобы посмотреть учебник для изучения React amp; Redux , или, если вы хотите только учиться redux , следуйте инструкциям с 34 по 43 от TheNetNinja