我有很多机会看到别人写的代码。我发现,在使用 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?(
{this.type?===?0?&&?}
{this.type?===?1?&&?}
{this.type?===?2?&&?}
)
}
}
在函数组件中
function?A({navigation})?{
const?type?=?navigation.getParams('type');
return?(
{type?===?0?&&?}
{type?===?1?&&?}
{type?===?2?&&?}
)
}
只有在组件内部有变化,并且变化会引起组件重新渲染的状态,我们才会把这些状态,使用 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?(
注册
)
}
我的问题是:
这样写,dosomething中的后续逻辑能正常执行吗?
使用 state 管理isRegister合理吗?
如果不应该使用 state 管理isRegister,那应该怎么办?
留给大家思考,相信大家都能找到答案。
领取专属 10元无门槛券
私享最新 技术干货