为什么在反应中以状态存储数据

时间:2019-05-01 04:30:51

标签: javascript reactjs

我想了解如果不将数据存储在state中会丢失什么。我们仍然可以使用this.setState({})触发重新渲染。请提供深入的分析。

请注意,我不关心维护应用程序的状态(通常通过Redux,Mobx等来完成)

class App extends React.Component {
  constructor() {
    super();
    // this.state = { counter: 0 };//Am I loosing something by not doing in this way
  }
  counter = 0;
  increament() {
    this.counter++;
    this.setState({});//trigger re-render as new object is set to state
    // this.state.counter++;
    // this.setState(this.state);
  }

  render() {
    return (
      <div>
        <h2>Click button to increament counter</h2>
        <button type="button" onClick={()=>this.increament()}>{this.counter}</button>
      </div>
    );
  }
}
//export default App;

ReactDOM.render(
  <App />,
  document.body
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

3 个答案:

答案 0 :(得分:3)

您将失去的最大的事情之一就是生命周期方法和可维护性。 React state背后的全部思想是使该组件以及从该状态传递数据的任何子组件中的数据保持同步变得更加容易,但是要使所有这些工作如预期的那样,您需要更新状态使用this.setState()并通过this.state从中读取。

React在调用this.setState()时所做的工作(除了更新状态外)还要经历必要的生命周期步骤。然后,它要做的主要事情之一就是重新渲染组件(它是子组件),但是正如您所说的,您可以使用this.setState({})触发它,在某种程度上是正确的,但是前提是您还可以输了:

性能

JavaScript快速。反应很快。当您快速穿越时会得到什么?我不知道,但这可能真的很快。特别是如果您喜欢使用React的PureComponent,它与Component完全一样,不同之处在于PureComponent使用浅层状态和props比较来实现shouldComponentUpdate,而{{1} }不会。这意味着如果您不进行任何更新(状态和道具都保持不变),则Component不会重新渲染组件,而PureComponent会重新渲染。如果您不使用React的状态系统,那么您就不能真正使用Component来获得更好的性能,也不能实现PureComponent,因为您无法将旧数据与新数据进行比较。您必须自己重新实现该性能功能。

稳定性

告别React的状态系统以支持hacky解决方案还意味着告别应用程序稳定性,并向更多的问题打招呼。让我们从以上几点考虑性能问题,并将其扩展。为了使您的应用程序性能更高,您必须对整个应用程序重复以上操作,或者创建一个通用解决方案,以便可以在各个组件之间重复使用。更不用说每次更新数据时都记得要调用shouldComponentUpdate的事实,只是使组件重新呈现。忘记一次,您的应用程序将开始显示不一致的数据,因为即使更新了“您的状态”,React的状态也没有。扩大规模,您就会遇到问题。

不想伤害您的同事

让我们面对现实吧。您可能是编程新手,还是React新手,或者没有团队合作,没关系,我们都是从某个地方开始的。不过,真正重要的是,不要让您的团队想伤害您,以至于您必须选择一个新的专业。一种不需要手指和/或眼睛的东西。 使用经过测试和测试的框架以及正确使用它们的好处是,每个人的麻烦都更少。无需为现有的用例创建和维护骇人的解决方案。无需因渲染不一致而将头发扯掉。 有人认为重塑方向盘是个好主意,但这一次是一个立方体。

TL; DR和结束语

  1. 不要重新发明轮子。它已经存在,并且是圆形的
  2. 聪明而不是辛苦
  3. 使用React的内置状态系统或Redux / MobX(请参阅1。)
  4. 使用this.setState({})进行更新,使用this.setState进行阅读。 Don't directly mutate state,因为React不会调用任何生命周期方法,从而导致意外的行为和错误

答案 1 :(得分:1)

在组件实例上设置组件状态会导致 buggy组件,并且会影响该组件的可维护性。

不能保证组件状态的正确性

如果您产生的点击次数的增长速度比this.counter的增长快,则不能保证计算出的counter是正确的

setState确保将对它的多个调用一起批处理以应用。 因此,保证了counter的值。

this.setState(prevState => ({counter: prevState.counter + 1}))

渲染逻辑与状态突变没有分离

此外,在某些情况下,当组件状态未更改时,您必须避免渲染,React.Component之类的生命周期方法(如shouldComponentUpdate)捕获下一个状态_有效地将渲染决定从更新变为州。

保持组件实例的状态将使您计算下一个状态,将其与上一个状态进行比较,并确定是否强制重新渲染。 如果您需要为组件管理更多状态,则可能难以维护。

答案 2 :(得分:-1)

我能想到的一件事是stateprops是反应中的大事。

例如,当您调用.setState时,并不是更新ui的触发器,而是排队的更新请求。

为什么重要? 几个原因(and more here):

  1. setState不一定表示该组件确实会重新呈现。如果状态保持与以前相同,则react将会注意到并会跳过渲染周期,从而提高性能(这是虚拟DOM之上的主要优势之一)。
  2. setState是异步的(通常),在单个渲染之前可能会发生多个setState。因此,setState({a:true});setState({a:false});从理论上讲可以跳过中间渲染(再次提高性能)。

另一件事是,反应成分只有一个真理来源。

这是一个设计原理,可以帮助简化代码的可读性,从而简化开发和调试过程。 React只是一个 View 框架(就像在MVC / MV *中一样,只是没有M)。其余的工作由您决定。由于它只是一个视图,因此组件实质上就是纯数据的HTML(或更确切地说,JSX)表示形式(或绑定,具体取决于词典)。 该数据是状态,因此具有特殊状态。 通过了解组件只是(state) => { <html>}函数,它使考虑(和编码)React变得更加容易。当您想查看状态变化的地方时,只需寻找setState。就如此容易。您当然可以将其他内容存储为类成员,但这会破坏简单性和可读性的目的。

* PS:以上内容也意味着时间旅行很容易。您只需将状态变化向后打(理论上),这也是使事情保持简单的一个很酷的好处。