简体   繁体   English

在 React 中 setState() 的最佳实践是什么?

[英]What is the best practice to setState() a class object in React?

So let's assume I have this code所以让我们假设我有这个代码

import {useState} from 'react'

class Something{
   counter:number
   constructor(counter:number){
      this.counter = counter
   }
}

function functionalComponent(){
   const [state, setState] = useState<Something>(new Something(5))

   //other codes .....

   function changeState(){
   //see below
   }

   return (
      <>
        <h1>{state.counter}</h1>
        <button onClick={changeState}>Increment</button>
      </>
   )
}

export default functionalComponent

Now at some point, I want to change the state to have counter increment 1, the below code works but...现在在某个时候,我想将 state 更改为计数器增量 1,下面的代码可以工作,但是......

   function changeState(){
      state.counter += 1
      setState(state)
   }

And before you all start shouting in the comments, I know that we shouldn't mutate the state directly and instead create a new state and pass it on to the setState.在大家开始在评论中大喊大叫之前,我知道我们不应该直接改变 state 而是创建一个新的 state 并将其传递给 setState。 But the thing is for js objects and arrays we can simply use the spread operators, but I couldn't find anything simpler for class objects.但是对于 js 对象和 arrays,我们可以简单地使用扩展运算符,但对于 class 对象,我找不到更简单的方法。

So my question is " What should be the best approach for situations like this? "所以我的问题是“对于这种情况,最好的方法应该是什么?

One I could think of and is using我能想到并正在使用的一个

   function changeState(){
      let newState = new Something(state.counter+1)
      setState(newState)
   }

But it becomes counter productive if my object contains many fields say 15但是,如果我的 object 包含许多字段,例如 15,它会适得其反

You can use your class inside an object and use the spread operator:您可以在 object 中使用 class 并使用扩展运算符:

const [state, setState] = useState({state:new Something(5)})

state.state.counter = 1
setState({...state})

While it would be technically possible to create a new Something every time you want to change the state:虽然从技术上讲,每次您想更改 state 时都可以创建一个新的Something

const [state, setState] = useState(5)
const something = useMemo(() => new Something(state), [state]);

I'd also first strongly consider whether you need a class inside a functional component at all - it's pretty odd.我还首先强烈考虑您是否需要在功能组件中使用 class - 这很奇怪。 There's probably a more intuitive solution.可能有一个更直观的解决方案。

Another option which may or may not work depending on what your actual code contains in the class constructor would be to have the state contain an object for all instance properties:根据您的实际代码在 class 构造函数中包含的内容,另一个可能会或可能不会起作用的选项是让 state 包含所有实例属性的 object:

const [state, setState] = useState({ counter: 5 });
const something = useMemo(() => Object.assign(new Something(), state), [state]);

Lets just use useState and functional components it would make your life way easier..让我们只使用 useState 和功能组件,它会让你的生活更轻松..

One Approach that I tried and seems to be close enough is to have a clone function in the class that returns a clone(new Instance).我尝试过并且似乎足够接近的一种方法是在 class 中有一个克隆 function ,它返回一个克隆(新实例)。 See the below example for a better understanding请参阅以下示例以获得更好的理解

class Something{
   counter:number
   constructor(counter:number){
      this.counter = counter
   }
   
   clone(){
      return new Something(this.counter)
   }
}

So this way whenever I'll call clone it will return a new Instance.因此,每当我调用 clone 时,它都会返回一个新的实例。 Now in the changeState function, we can do现在在changeState function,我们可以做

   function changeState(){
      let newState = state.clone()
      newState.counter += 1
      setState(newState)
   }

These steps ensures that no where the data is mutated as adheres to the principal of React.这些步骤确保了数据不会发生变异,因为它符合 React 的原则。

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

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