简体   繁体   English

为什么要将数据存储在状态中

[英]Why to store data in state in react

I want to understand what we lose if we don't store the data in state . 如果我们不将数据存储在state我想了解我们失去了什么。 We can still trigger re-render by using this.setState({}) . 我们仍然可以使用this.setState({})触发重新渲染。 Please provide in-depth analysis. 请提供深入分析。

Note that I am not concerned to maintain the state of application(usually done via Redux, Mobx etc.) 请注意,我并不担心维护应用程序的状态(通常通过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; increment() { 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> 

One of the biggest things you'd lose are lifecycle methods and maintainability. 您失去的最重要的事情之一是生命周期方法和可维护性。 The whole idea behind React's state is to make it easier to keep data in sync both in that component and in any child components being passed data from that state, but for all that to work as intended, you need to update the state using this.setState() and read from it through this.state . React state背后的整个想法是更容易使数据在该组件和从该状态传递数据的任何子组件中保持同步,但是对于所有按预期工作的情况,您需要使用this.setState()更新状态this.setState()并通过this.state读取。

What React does when calling this.setState() (besides updating the state) is go through the necessary lifecycle steps as well. React在调用this.setState() (除了更新状态之外)也会执行必要的生命周期步骤。 One of the main things it does then is re-render the component (and it's children), but as you said, you can trigger that using this.setState({}) which to some extent is true, but only if you're also okay with losing: 它所做的主要事情之一是重新渲染组件(以及它的子组件),但正如你所说,你可以使用this.setState({})触发它,这在某种程度上是正确的,但只有你是失败也没关系:

Performance 性能

JavaScript is fast. JavaScript很快。 React is fast. 反应很快。 What do you get when you cross fast with fast? 当你快速快速穿越时,你会得到什么? I don't know, but it's probably something really fast. 我不知道,但它可能真的很快。 Especially if you like using React's PureComponent , which is exactly the same as Component with the difference that PureComponent implements shouldComponentUpdate using shallow state and props comparison, whereas Component doesn't. 特别是如果你喜欢使用作出反应的PureComponent ,这是完全一样的Component与区别PureComponent实现shouldComponentUpdate使用浅状态和道具比较,而Component没有。 What this means is that if you don't update anything (state and props both stay the same), the PureComponent won't re-render the component, whereas Component will. 这意味着如果你不更新任何东西(状态和道具都保持不变), PureComponent将不会重新渲染组件,而Component会重新渲染。 If you don't use React's state system, you can't really use PureComponent for better performance, nor can you implement shouldComponentUpdate , since you can't compare your old data with your new data. 如果您不使用React的状态系统,则无法真正使用PureComponent获得更好的性能,也无法实现shouldComponentUpdate ,因为您无法将旧数据与新数据进行比较。 You'd have to re-implement that performance feature yourself. 您必须自己重新实现该性能功能。

Stability 稳定性

Saying goodbye to React's state system in favor of a hacky solution also means saying goodbye to application stability, and saying hello to more problems down the road than you can count. 与React的状态系统说再见,支持hacky解决方案也意味着告别应用程序稳定性,并在未来的道路上向你问好。 Let's take the performance problems from the above point, and let's put them to scale. 让我们从上面的角度来看待性能问题,让我们把它们放大。 In order for you to have a more performant application, you'd have to either repeat the above for the whole application, or create a generic solution that you could re-use across components. 为了使您拥有更高性能的应用程序,您必须为整个应用程序重复上述操作,或者创建一个可以跨组件重用的通用解决方案。 Not to mention the fact that remembering to call this.setState({}) every time you update the data, just to make the component re-render. 更不用说每次更新数据时都记得要调用this.setState({})这一事实,只是为了让组件重新渲染。 Forget it once, and your application will start to display inconsistent data, because even though "your state" updated, React's state hasn't. 忘了一次,你的应用程序将开始显示不一致的数据,因为即使“你的状态”更新,React的状态也没有。 Scale that up, and you've got a problem. 扩大规模,你就遇到了问题。

Colleagues that don't want to hurt you 不想伤害你的同事

Let's face it. 面对现实吧。 You're probably either new to programming, new to React, or haven't worked in a team, and that's okay, we all start from somewhere. 你可能不是编程的新手,也不是React的新手,或者没有在团队中工作过,而且没关系,我们都是从某个地方开始的。 What's really important, though, is not making your team want to hurt you so bad you'd have to pick a new specialty. 然而,真正重要的是,不要让你的团队想要伤害你这么糟糕,你必须选择一个新专业。 One that doesn't require fingers and/or eyes. 一个不需要手指和/或眼睛的人。 The benefit of using tried and tested frameworks, as well as using them correctly, is that there's less hassle for everybody. 使用经过测试和测试的框架以及正确使用它们的好处是,每个人都可以减少麻烦。 Nobody has to create and maintain hacky solutions to already existing use cases. 没有人必须为现有的用例创建和维护hacky解决方案。 Nobody has to tear their hair out due to inconsistent rendering. 由于渲染不一致,没有人必须撕掉头发。 Nobody has to lose an eye or break any fingers because somebody thought it'd be a good idea to reinvent the wheel, but this time as a cube. 没有人不得不失去眼睛或打破任何手指,因为有人认为重新发明轮子是个好主意,但这次是一个立方体。

TL;DR & Final words TL; DR和最后的话

  1. Don't reinvent the wheel. 不要重新发明轮子。 It already exists, and it's round 它已经存在,而且它是圆的
  2. Work smart, not hard 工作聪明,不难
  3. Either use React's built-in state system or Redux/MobX (see 1.) 使用React的内置状态系统或Redux / MobX(参见1.)
  4. Use this.setState for updating, this.state for reading. 使用this.setState进行更新,使用this.state进行读取。 Don't directly mutate state , as React won't call any lifecycle methods, resulting in unexpected behavior and bugs 不要直接改变状态 ,因为React不会调用任何生命周期方法,导致意外的行为和错误

Setting component state on a component instance can lead to buggy component and have an impact on maintability of the component. 在组件实例上设置组件状态可能会导致组件错误,并对组件的维护性产生影响。

Correctness of Component state isn't guaranteed 组件状态的正确性无法保证

If you generate clicks faster than this.counter is incremented, the computed counter isn't guaranteed to be correct . 如果您生成的点击次数比this.counter增加的速度快, 则无法保证计算的counter是正确的

setState guarantees that multiple calls to it are batched together to be applied. setState保证对它的多个调用一起批处理以应用。 For this reason, counter value is guaranteed. 因此,保证counter价值。

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

No separation of rendering logic from state mutation 没有将渲染逻辑与状态变异分开

Also, in use cases where you have to avoid a render when the component state didn't change, React.Component lifecycle methods like shouldComponentUpdate captures the next state _effectively separating the decision to render from update to state. 此外,在那里你必须避免渲染当组件的状态没有改变的情况下使用, React.Component生命周期方法,如shouldComponentUpdate捕捉下一个状态_effectively分开来呈现来自更新状态的决定。

Keeping state on the component instance will have you computing the next state, comparing it to the previous one and deciding whether to force a rerender. 在组件实例上保持状态将使您计算下一个状态,将其与前一个状态进行比较并决定是否强制重新呈现。 This can become difficult to maintain if you have more state to manage for the component. 如果您有更多的状态来管理组件,这可能会变得难以维护。

One specific thing I can think of is that state and props are big things in react. 我能想到的一件具体事情是stateprops是反应中的大事。

For instance, when you call .setState it isn't exactly a trigger to update ui but rather a queued update request. 例如,当您调用.setState它不是更新ui触发器,而是更新排队的更新请求。

Why does it matter? 为什么这有关系? Several reasons ( and more here ): 有几个原因( 以及更多 ):

  1. A setState doesn't necessarily mean that the component will indeed re-render. setState并不一定意味着组件确实会重新渲染。 if the state is left the same as before, react will notice, and will skip the render cycle which gives you a performance boost (and is one of the key advantages on top of the virtual DOM). 如果状态与之前保持一致,则会发出反应,并且将跳过渲染周期,这会提高性能(并且是虚拟DOM之上的关键优势之一)。
  2. setState is async (usually), and several setState can happen before a single render. setState是异步(通常),并且在单个渲染之前可以发生几个setState。 thus, setState({a:true});setState({a:false}); 因此, setState({a:true});setState({a:false}); can in theory just skip the intermediate render (performance boost again). 理论上可以跳过中间渲染(再次提升性能)。

One other thing is the idea that there is only one source of truth to a react component. 另一件事是反应组件只有一个真实来源。

This is a design principal that allows easier development and debugging as it helps with code readability. 这是一个设计原则,允许更容易的开发和调试,因为它有助于代码可读性。 React is just a View framework (as in MVC / MV*, just without the M). React只是一个View框架(就像在MVC / MV *中一样,没有M)。 It is up to you to do the rest. 由你来完成剩下的工作。 Since it is just a View, Components are essentially just HTML (or rather, JSX) representation (or bindings, depending on lexicon) of plain data. 由于它只是一个视图,因此组件基本上只是普通数据的HTML(或更确切地说,JSX)表示(或绑定,取决于词典)。 That data is state , and therefor has a special status. 该数据是状态 ,因此具有特殊状态。 It makes it much easier to think of (and code) React, with the understanding the Components are just (state) => { <html>} functions. 通过理解组件只是(state) => { <html>}函数,可以更容易地想到(和代码)React。 when you want to see where the state changes, you just look for setState . 当您想要查看状态更改的位置时,您只需查找setState as simple as that. 就如此容易。 you could of course store other things as class members, but that would defeat the purpose of simplicity and readability. 当然,您可以将其他东西存储为类成员,但这会破坏简单性和可读性的目的。

*PS: the above also means that time-travel is easy. * PS:以上也意味着时间旅行很容易。 you just play the state changes backwards (in theory) which is also a cool benefit of keeping things simple. 你只是向后发挥状态变化(在理论上),这也是保持简单的一个很好的好处。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM