我正在阅读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回调的范围?


当前回答

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}`);
}

其他回答

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

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

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

访问。由于setState方法的异步特性,在调用setState方法后,不能保证返回更新后的状态。

为了保证在调用setState之后进行更新,可以采用两种解决方案。

解决方案1:正如上述答案之一所提到的,将代码放在componentDidUpdate方法中

解决方案2:正如上面的另一个答案所提到的,将你的东西作为一个回调传递

 this.setState({value: myValue}, function () {
    this.functionThatIsExecutedWhenStateIsUpdated();
});

需要注意的是,这两种解决方案并不能明显互换。一个不能轻易地解决另一个的所有用例。作为一般规则,如果可以的话,最佳实践建议首选解决方案1。但是,在一些用例中,只有解决方案2“更有效”地工作,例如“更新我的视图和提交我的数据”用例。这个用例是这样的:

在添加一个项目后,说,“添加日程”,我想将该项目添加到前端列表,并立即将刚刚更新的列表发布到后端,如下面的概念所示:

如果你不做任何解决方案,也就是说,如果你只在你的代码中这样说:

addToItemArray = () => { 
     this.setState{{ scheduledItemsArray: newObjectListWithMax}}   
     this.postData();
}

<button className="btn btn-secondary btn-block" onClick={this.addToItemArray}>Add Shedule</button>

... 你将发布列表排除“Delivery to Max”项,因为当你this.postData()时状态不会更新(同样,因为它是异步的)。

如果您使用解决方案1,您将在输入日程名称文本框中的每个字符后进行POST !

还有其他方法来满足这个用例,但是解决方案2在阅读代码时最好地传达了意图。

考虑到这个用例在几乎每个web应用程序中无处不在的本质,Michael的回答中解释的回调技术是每个开发人员工具包中不可或缺的一段代码。

来自React的文档:

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

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

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

您可以尝试使用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}`);
}