#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