Состояние init без конструктора в реакции
import React, { Component } from 'react';
class Counter extends Component {
state = { value: 0 };
increment = () => {
this.setState(prevState => ({
value: prevState.value + 1
}));
};
decrement = () => {
this.setState(prevState => ({
value: prevState.value - 1
}));
};
render() {
return (
<div>
{this.state.value}
<button onClick={this.increment}>+</button>
<button onClick={this.decrement}>-</button>
</div>
)
}
}
Обычно я видел, что люди делают this.state в функции конструктора, если он использовал класс es6. Если он не, он, вероятно, ставит государство, используя функцию getinitialstate. Но над кодом (да это рабочий код), не использовал ни то, и другое. У меня есть 2 вопроса, что здесь здесь? является локальной переменной? если да, то почему у него нет const
? откуда происходит превалирование? почему функция стрелок используется в setState? не так просто сделать this.setState({value:'something'})
?
Ответы
Ответ 1
О вопросе 2, см. Дан, отличный ответ здесь: Нужно ли мне использовать перегрузку setState (function) в этом случае?
-
Нет, это не локальная переменная. Это то же самое, что объявление this.state
в конструкторе.
-
Да, в этом случае вы можете просто использовать this.setState({ value: this.state.value + 1 })
, результат будет таким же.
Но обратите внимание, что с помощью функционального setState
вы можете получить некоторые преимущества:
-
функция setState может быть повторно использована, если вы объявите ее снаружи:
const increment = prevState => ({
value: prevState.value + 1
})
теперь, если у вас есть несколько компонентов, которые должны использовать эту функцию, вы можете просто импортировать и повторно использовать логику везде.
this.setState(increment)
-
Реагирует squashes на несколько setState
и выполняет их в пакетном режиме. Это может привести к неожиданному поведению. См. Следующий пример:
http://codepen.io/CodinCat/pen/pebLaZ
add3 () {
this.setState({ count: this.state.count + 1 })
this.setState({ count: this.state.count + 1 })
this.setState({ count: this.state.count + 1 })
}
выполнение этой функции count
будет только плюс 1
Если вы используете функциональный setState:
http://codepen.io/CodinCat/pen/dvXmwX
const add = state => ({ count: state.count + 1 })
this.setState(add)
this.setState(add)
this.setState(add)
count будет +3, как вы ожидали.
Вы можете увидеть документы здесь: https://facebook.github.io/react/docs/react-component.html#setstate
Ответ 2
У меня есть 2 вопроса, что здесь state
?
Свойство экземпляра, например, установка this.state = {value: 0};
в конструкторе. Он использует предложение Public Class Fields в настоящее время на этапе 2. (Итак, increment
и decrement
, которые являются полями экземпляров, значениями которых являются стрелка функции, поэтому они закрываются на this
.)
- локальная переменная?
Нет.
откуда берется prevState? почему функция стрелок используется в setState? не так просто сделать this.setState({значение: 'something'})?
Из документация:
React может выполнять несколько вызовов setState()
в одно обновление для производительности.
Поскольку this.props
и this.state
могут обновляться асинхронно, вы не должны полагаться на их значения для вычисления следующего состояния.
Например, этот код может не обновить счетчик:
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});
Чтобы исправить это, используйте вторую форму setState()
, которая принимает функцию, а не объект. Эта функция получит предыдущее состояние в качестве первого аргумента и реквизит в момент применения обновления в качестве второго аргумента:
// Correct
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));
... это именно то, что делает котируемый код. Это было бы неправильно:
// Wrong
increment = () => {
this.setState({
value: this.state.value + 1
});
};
... потому что он полагается на состояние this.state
, которое выше не говорит нам; поэтому цитируемый код делает это вместо:
increment = () => {
this.setState(prevState => ({
value: prevState.value + 1
}));
};
Здесь доказательство того, что React может прерывать вызовы неочевидным образом и почему нам нужно использовать обратную версию setState
: Здесь мы имеем increment
и decrement
, вызываемые дважды за клик, а не один раз ( один раз кнопкой, один раз по диапазону, содержащему кнопку). При щелчке +
один раз нужно увеличить счетчик до 2, потому что increment
вызывается дважды. Но поскольку мы не использовали функцию обратного вызова функции setState
, это не так: один из этих вызовов в increment
становится no-op, потому что мы используем устаревшее значение this.state.value
:
class Counter extends React.Component {
state = { value: 0 };
increment = () => {
/*
this.setState(prevState => ({
value: prevState.value + 1
}));
*/
console.log("increment called, this.state.value = " + this.state.value);
this.setState({
value: this.state.value + 1
});
};
fooup = () => {
this.increment();
};
decrement = () => {
/*
this.setState(prevState => ({
value: prevState.value - 1
}));
*/
console.log("decrement called, this.state.value = " + this.state.value);
this.setState({
value: this.state.value - 1
});
};
foodown = () => {
this.decrement();
};
render() {
return (
<div>
{this.state.value}
<span onClick={this.fooup}>
<button onClick={this.increment}>+</button>
</span>
<span onClick={this.foodown}>
<button onClick={this.decrement}>-</button>
</span>
</div>
)
}
}
ReactDOM.render(
<Counter />,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>