我正在阅读reactjs文档的表单部分,只是尝试了这段代码来演示onChange的用法(JSBIN)。

var React= require('react');

var ControlledForm= React.createClass({
    getInitialState: function() {
        return {
            value: "initial value"
        };
    },

    handleChange: function(event) {
        console.log(this.state.value);
        this.setState({value: event.target.value});
        console.log(this.state.value);

    },

    render: function() {
        return (
            <input type="text" value={this.state.value} onChange={this.handleChange}/>
        );
    }
});

React.render(
    <ControlledForm/>,
  document.getElementById('mount')
);

当我在浏览器中更新<input/>值时,handleChange回调中的第二个console.log打印与第一个console.log相同的值,为什么我看不到这个结果。setState({value: event.target.value})在handleChange回调的范围?


当前回答

正如React文档中提到的,没有保证setState被同步触发,所以你的console.log可能会在更新之前返回状态。

Michael Parker提到在setState中传递一个回调。另一种处理状态改变后逻辑的方法是通过componentDidUpdate生命周期方法,这是React文档中推荐的方法。

通常,我们建议对这种逻辑使用componentDidUpdate()。

当可能连续触发了setStates,并且您希望在每次状态更改后都触发相同的函数时,这特别有用。您可以将函数放置在componentDidUpdate中,而不是向每个setState添加回调,如果需要的话,在其中使用特定的逻辑。

// example
componentDidUpdate(prevProps, prevState) {
  if (this.state.value > prevState.value) {
    this.foo();  
  }
}

其他回答

来自React的文档:

setState()不会立即改变它。状态,但创建了 挂起状态转换。访问。调用后的状态 方法可能返回现有的值。没有 保证调用setState和调用may的同步操作 批处理以获得性能提升。

如果希望在状态改变发生后执行函数,可以将其作为回调传入。

this.setState({value: event.target.value}, function () {
    console.log(this.state.value);
});

有时这种问题会发生在状态中。 对于钩子,你应该使用useEffect钩子,如下所示-

const [fruit, setFruit] = useState('');
 
setFruit('Apple');
useEffect(() => {
  console.log('Fruit', fruit);
}, [fruit])

这救了我的一天,希望会帮助你!!

正如React文档中提到的,没有保证setState被同步触发,所以你的console.log可能会在更新之前返回状态。

Michael Parker提到在setState中传递一个回调。另一种处理状态改变后逻辑的方法是通过componentDidUpdate生命周期方法,这是React文档中推荐的方法。

通常,我们建议对这种逻辑使用componentDidUpdate()。

当可能连续触发了setStates,并且您希望在每次状态更改后都触发相同的函数时,这特别有用。您可以将函数放置在componentDidUpdate中,而不是向每个setState添加回调,如果需要的话,在其中使用特定的逻辑。

// example
componentDidUpdate(prevProps, prevState) {
  if (this.state.value > prevState.value) {
    this.foo();  
  }
}

您可以尝试使用ES7 async/await。举个例子:

handleChange: async function(event) {
    console.log(this.state.value);
    await this.setState({value: event.target.value});
    console.log(this.state.value);
}

Async-await语法非常适合以下内容:

changeStateFunction = () => {
  // Some Worker..

  this.setState((prevState) => ({
  year: funcHandleYear(),
  month: funcHandleMonth()
}));

goNextMonth = async () => {
  await this.changeStateFunction();
  const history = createBrowserHistory();
  history.push(`/calendar?year=${this.state.year}&month=${this.state.month}`);
}

goPrevMonth = async () => {
  await this.changeStateFunction();
  const history = createBrowserHistory();
  history.push(`/calendar?year=${this.state.year}&month=${this.state.month}`);
}