为什么 React 现在要推行函数式组件,用 class 不好吗?
65 个回答
一些同学可能认为“函数式组件+useState”不就是有状态了吗,不就是class组件的另一种写法吗?只不过更优雅一些?
我认为fb团队花那么大的力气,拽着整个React社区往一个前所未有的方向前进,原因肯定不仅仅是“写法更优雅”。真正的原因如下:
- Hooks是比 HOC 和 render props 更优雅的逻辑复用方式。这个是很多人喊“真香”的原因。优雅的逻辑复用方式,会促进一个更加蓬勃的生态,这对于原本生态就很强的React来说是如虎添翼。会有更多的人愿意把自己的逻辑抽离成hooks(因为真的太优雅了),发布为library,为react生态添砖加瓦(看看这段时间各种基于hooks的状态管理工具)。我还认为,很快会出现一些“hooks生态圈”的“lodash”。
- 函数式组件的心智模型更加“声明式”。hooks(主要是useEffect)取代了生命周期的概念(减少API),让开发者的代码更加“声明化”:
- 旧的思维:“我在这个生命周期要检查props.A和state.B(props和state),如果改变的话就触发xxx副作用”。这种思维在后续修改逻辑的时候很容易漏掉检查项,造成bug。
- 新的思维:“我的组件有xxx这个副作用,这个副作用依赖的数据是props.A和state.B”。从过去的 命令式 转变成了 声明式 编程。
- 其实仔细想一想,人们过去使用生命周期不就是为了判断执行副作用的时机吗? 现在hooks直接给你一个声明副作用的API,使得生命周期变成了一个“底层概念”,无需开发者考虑。开发者工作在更高的抽象层次上了。
- 类似的道理,除了声明副作用的API,react还提供了声明“密集计算”的API(useMemo),取代了过去“在生命周期做dirty检查,将计算结果缓存在state里”的做法。React内核帮你维护缓存,你只需要声明数据的计算逻辑以及数据的依赖。
3. 函数式组件的心智模型更加“函数式”。react团队正在循序渐进地 教育社区 ,为未来的并发模式打下基础。(其实react从一开始就受到了很多函数式编程的影响,现在推行函数式组件算是“回归初心”)。下面我会详细讨论函数式组件的心智模型。
函数式组件的心智模型
函数式组件绝不仅仅是“另一种写法的class组件”,它和class的组件在心智模型还是存在很大差别的。 函数式组件依然是【外部数据=>view】的映射,依然是pure function的心智模型。 只不过现在外部数据不仅仅包括props和context,还包括state。
事实上,未来的并发模式就要求你使用pure function的心智模型来编写函数式组件,否则很容易出bug。
state是一种外部数据
有同学可能会问:“你在逗我吧?都useState了你还pure呢???”
但是你发现没有,react对hooks的 种种限制 ,不就是为了让你把useState等hooks 声明 在函数组件的开头?useState状态声明在概念上相当于 静态声明 ,不会因为【props这种运行时因素】的变化而改变。你完全能写个代码分析工具,无需运行代码就能收集所有状态声明。
静态声明一个state,不就相当于用一个Wrapper组件来持有这个状态,然后传给它?那这个state不就可以理解为一种外部输入? 举个例子:
// MyComp看起来好像有状态,不是纯函数 :(
function MyComp() {
const [state, setState] = useState(0)
return <div>{state}</div>
}
其实相当于
// MyComp现在看起来更像一个纯函数了吧!
function MyComp({state, setState}) {
// 开发者编写的组件代码,只不过剔除了useState声明
return <div>{state}</div>