「React」很多人在滥用 state

时间:2022-07-22
本文章向大家介绍「React」很多人在滥用 state,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

我有很多机会看到别人写的代码。我发现,在使用 React 时,很多人都在滥用 state。

群里有个朋友提问,上图是我们的部分对话过程。

他希望将从路由传过来的参数 type 保存到组件的state中,然后在 render 中使用。

于是,他就有了一个困扰,既然 type 要保存到 state 中,那我应该在哪个生命周期去获取它呢?

很显然,这个小伙伴,自己给自己下了个套。

在后续的沟通得知,他希望从 url 中,获取到传入的 type 类型,然后根据不同的 type ,渲染出来不同的组件。

我们仔细思考一下,这样场景之下的一个状态,type,适合放在 state 中吗?

在回答这个问题之前,我们来总结一下,React state 的特性。

在 React 哲学思维中,state 非常特别,当我们使用 setState 改变 state 中的属性时,会引起组件的重新渲染。

实际上,如果抛开 React,我们来看 state,无论是 class 组件,还是 hooks 组件,state 并无特别。

class A {
  state: {
    a: 1
  }
}

在对象 A 的内部,我们可以使用正常的操作方式,去修改它。

this.state.a = 2

而实际上,在 React 的官网中,特别明确的强调了,不要直接使用这样的方式去修改 state

在 React 看来,state 有特殊的职能,它应该保存那些能够让组件重新渲染的状态。

那么也就意味着,在 React 的设计思维里,它并不希望你把任何状态都放在 state 中来管理。

结合上诉的案例分析,从路由传过来的参数 type,在当前组件中,并没有修改的必要。当然接收到的 type 值会不一样,却不是在当前组件内部进行修改的。

那 type 在当前组件不修改,但是我要在很多地方使用到它,应该如何处理呢?

如下:

在 class 组件中

class A extends React.Component {
  type = this.props.navigation.getParams('type');

  render() {
    return (
      <div>
        {this.type === 0 && <SomeComponent1 />}
        {this.type === 1 && <SomeComponent2 />}
        {this.type === 2 && <SomeComponent3 />}
      </div>
    )
  }
}

在函数组件中

function A({navigation}) {
  const type = navigation.getParams('type');
  return (
    <div>
      {type === 0 && <SomeComponent1 />}
      {type === 1 && <SomeComponent2 />}
      {type === 2 && <SomeComponent3 />}
    </div>
  )
}

只有在组件内部有变化,并且变化会引起组件重新渲染的状态,我们才会把这些状态,使用 state 来管理。

正是由于没有正确悟透 state 的使用,导致在具体开发时,常常会产生非常多的疑问。

例如下面这个简单的案例大家可以思考一下。

非常多的人,在初学 React 时,都会这样使用,也有可能,你正在这样使用。

使用 state 来管理一个是否注册的状态 isRegister

注册成功之后,通过 setIsRegister 修改 isRegister 的状态为 true。修改之后,马上执行 dosomething 逻辑。

dosomething 中,为了逻辑更健壮,判断如果 isRegister 仍然为 false,则什么也不做。只有当 isRegister = true 时,才执行后续逻辑。

function Foo() {
  const [isRegister, setIsRegister] = useState(false)

  function dosomething() {
    // 如果没注册,什么逻辑也不执行
    if (!isRegister) {
      return;
    }
    // todo
    history.go('xxxxxx/a/b/c');
    // 。。。
  }

  function register() {
    api.register().then(() => {
      // 注册成功,执行函数 A,在A 中,使用 isRegistor 判断了逻辑
      setIsRegister(true)
      dosomething()
    })
  }

  return (
    <button onClick={register}>注册</button>
  )
}

我的问题是:

这样写,dosomething 中的后续逻辑能正常执行吗?

使用 state 管理 isRegister 合理吗?

如果不应该使用 state 管理 isRegister,那应该怎么办?

留给大家思考,相信大家都能找到答案。