react中没有构造函数的初始化状态

IT技术 javascript reactjs
2021-03-26 09:10:05
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>
    )
  }
}

通常我看到的是如果他使用 es6 类,人们会在构造函数中执行 this.state 。如果他不是,他可能会使用 getinitialstate 函数放置状态。但是上面的代码(是的,它是一个工作代码),两者都没有使用。我有两个问题,这里的状态是什么?那是局部变量吗?如果是,为什么没有constprevState 来自哪里?为什么在 setState 中使用箭头函数?做这件事不是很容易this.setState({value:'something'})吗?

3个回答

我有两个问题,state这里是什么?

一个实例属性,就像this.state = {value: 0};在构造函数中设置一样它正在使用目前处于第 2 阶段公共类字段提案。(也是incrementdecrement,它们是实例字段,其值为箭头函数,因此它们关闭了this。)

那是局部变量吗?

不。

prevState 来自哪里?为什么在 setState 中使用箭头函数?只做 this.setState({value:'something'}) 不是很容易吗?

文档

setState()为了提高性能,React 可以将多个调用批处理为单个更新。

因为this.propsthis.state可能会异步更新,所以您不应该依赖它们的值来计算下一个状态。

例如,此代码可能无法更新计数器:

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});

要修复它,请使用setState()接受函数而不是对象的第二种形式该函数将接收先前的状态作为第一个参数,并将应用更新时的 props 作为第二个参数:

// 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因为我们使用了一个陈旧的this.state.value,所以这些调用之一变成了一个空操作

使用函数回调,它可以正常工作(没有调用increment变为无操作):

在这种情况下,当然,我们可以查看该render方法并说“嘿,increment在单击过程中会被调用两次,我最好使用 的回调版本setState。” 但是,与其假设this.state在确定下一个状态时使用它是安全的,最好的做法是不要假设它。在复杂的组件中,很容易以 mutator 方法的作者可能没有想到的方式使用 mutator 方法。因此 React 作者的声明:

因为this.propsthis.state可能会异步更新,所以您不应该依赖它们的值来计算下一个状态

@JennyMok:“没有错”——是的,有。仅仅因为它还没有咬你,并不意味着它没有任何问题。请参阅文档。React 开发人员可能比我们更了解 React,并且不只是随心所欲地添加这个接受函数的表单。
2021-05-28 09:10:05
我用了很多this.setState({ value: this.state.value + 1 });它至少有效,没有错。我没有遇到任何问题。
2021-06-10 09:10:05

关于问题 2,请参考 Dan 的精彩回答:在这种情况下,我需要使用 setState(function) 重载吗?


  1. 不,它不是局部变量。这与this.state在构造函数中声明相同

  2. 是的,在这种情况下,您可以只使用this.setState({ value: this.state.value + 1 }),结果将是相同的。

但请注意,通过使用函数式,setState您可以获得一些好处:

  1. 如果在外部声明 setState 函数,则可以重用它:

    const increment = prevState => ({
      value: prevState.value + 1
    })
    

    现在如果你有几个组件需要使用这个功能,你可以在任何地方导入和重用逻辑。

    this.setState(increment)
    
  2. React 压缩几个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)
    

    如您所料,计数将 +3。

您可以在此处查看文档:https : //facebook.github.io/react/docs/react-component.html#setstate

请参阅我的答案结尾以证明这不是真的。批处理可以以不明显的方式发生;编写依赖于this.statemutator 的代码是一种糟糕的做法。同样,React 开发人员setState 出于某种原因创建了 的函数版本
2021-05-25 09:10:05
当您在单个处理程序中多次调用 setState 时,React 仅批处理 setState,因此如果您的函数仅包含 1 个 setState,则它是安全的
2021-06-02 09:10:05
“是的,在那种情况下,您可以使用this.setState({ value: this.state.value + 1 }),结果将是相同的。” 完全不正确,因为我在我的回答中指出的文档(以及你在你的结尾)非常清楚地说明了这一点。说“你可以只使用[它]”是完全错误的。
2021-06-04 09:10:05
我的意思increment是OP的代码功能,只有1个setState语句,那就可以了
2021-06-12 09:10:05
不,不是。来自文档:为了提高性能,React可以将多个setState()调用批处理为单个更新......”(我的重点)。因此,如果有多次调用incrementReact 认为它可以批处理(即使从代码中看不出它可以批处理),它会;结果将是错误的。如果只是你故意setState反复打电话,你自己就能解决。
2021-06-19 09:10:05

对问题 1 的回答:

是的,您可以在没有构造函数的情况下为 React 类组件初始化状态:

class Counter extends Component {
  state = { value: 0 };

  handleIncrement = () => {
    this.setState(prevState => ({
      value: prevState.value + 1
    }));
  };

  handleDecrement = () => {
    this.setState(prevState => ({
      value: prevState.value - 1
    }));
  };

  render() {
    return (
      <div>
        {this.state.value}

        <button onClick={this.handleIncrement}>+</button>
        <button onClick={this.handleDecrement}>-</button>
      </div>
    )
  }
}

它使用类字段声明您可以在此处查看示例应用程序你也可以在 React 函数组件中使用 state(没有构造函数),但是使用高阶组件或渲染 prop 组件。您可以在此处了解更多信息

问题 2 的答案:在 React 中使用this.setState. 您可以使用对象或函数。如果您不依赖组件的 props 或 state 来更新其状态,则该对象很好。如果您依赖 props 或 state,则应该使用该函数,因为它始终具有执行时最新的 props 和 state。所有这一切都是因为this.setState()是异步执行的,因此在使用对象而不是函数更新本地状态时,您可以使用陈旧的状态或props。您可以在此处阅读更多相关信息

对于您仅在组件的本地空间中初始化状态的方式{...就在此处...} 您能否获得对 props 的引用以使用 likethis.props.value而不是state = { value: 0 }ie来初始化状态值,而不是像我想要的那样没有构造函数: state = { value: this.props.value } - 可能不可能吧?
2021-06-09 09:10:05