我有很多机会看到别人写的代码。我发现,在使用 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
,那应该怎么办?
留给大家思考,相信大家都能找到答案。