Зачем вообще использовать оператор распространения?
Оператор распространения ...
часто используется для создания мелких копий массивов или объектов. Это особенно полезно, когда вы стремитесь избежать изменения значений, что поощряется по разным причинам. TLDR; Код с неизменяемыми значениями гораздо проще рассуждать. Длинный ответ здесь .
Почему оператор спреда так часто используется в реакции?
В реакции это Настоятельно рекомендуется , чтобы избежать мутации this.state
и вместо этого вызвать this.setState(newState)
. Непосредственное изменение состояния не вызовет повторную визуализацию и может привести к ухудшению UX, неожиданному поведению или даже ошибкам. Это потому, что это может привести к тому, что внутреннее состояние будет отличаться от состояния, которое отображается.
Чтобы избежать манипулирования значениями, стало обычной практикой использование оператора распространения для создания производных объектов (или массивов), без изменения оригинала:
// current state
let initialState = {
user: "Bastian",
activeTodo: "do nothing",
todos: ["do nothing"]
}
function addNewTodo(newTodo) {
// - first spread state, to copy over the current state and avoid mutation
// - then set the fields you wish to modify
this.setState({
...this.state,
activeTodo: newTodo,
todos: [...this.state.todos, newTodo]
})
}
// updating state like this...
addNewTodo("go for a run")
// results in the initial state to be replaced by this:
let updatedState = {
user: "Bastian",
activeTodo: "go for a run",
todos: ["do nothing", "go for a run"]
}
Почему в этом примере используется оператор распространения?
Вероятно, чтобы избежать случайного изменения состояния. Хотя Array.filter()
не изменяет исходный массив и безопасен для использования в состоянии реакции, есть несколько других методов, которые изменяют исходный массив и не должны использоваться в состоянии. Например: .push()
, .pop()
, .splice()
. Распространяя массив перед вызовом над ним операции, вы гарантируете, что не изменяете состояние. При этом, я считаю, что автор сделал опечатку и вместо этого собирался сделать следующее:
delTodo = id => {
this.setState({
todos: [...this.state.todos].filter(todo => todo.id !== id)
});
};
Если вам нужно использовать одну из мутирующих функций, вы можете использовать их с распространением в Чтобы избежать изменения состояния и возможных ошибок в вашем приложении, выполните следующие действия:
// here we mutate the copied array, before we set it as the new state
// note that we spread BEFORE using an array method
this.setState({
todos: [...this.state.todos].push("new todo")
});
// in this case, you can also avoid mutation alltogether:
this.setState({
todos: [...this.state.todos, "new todo"]
});