导语:复杂业务逻辑复用一直是React组件开发中的一大难题,团队目前同质化业务比较多,我们的想法是直接复用已有的逻辑代码,因为还要考虑到数据的拉取,展示,显然纯UI组件不能满足我们的需求。前段时间也在复杂业务组件抽取上下了不少功夫。本文将使用近期非常火的React Hook特性抽取常用的业务组件,并比对业界已有方式,借此尝试探索出一套优雅的组件复用方案。背景现有的业务采用Redux管理业务数据,各模块关注的Reducer、Action是分散的,并且所有数据使用唯一Store储存。如果直接通过拷代码的方式,需要同时关注Reducer、Action目录,然后修改顶层Store中关注的Reducer。这样的开发方式对二次开发者来说非常不友好,理清原有代码然后复用的时间消耗不亚于自己重写一套逻辑。为了减少不必要的开发耗时,封装常用的复杂业务模块迫在眉睫。现阶段方式首先我们将开发方式由纵向开发转为横向开发。即将同一业务模块的Reducer、Action、index放置同一文件夹。目录结构如下:component |———reducer |———action |———accets |___index.js |___index.less这样还是和原始React+Redux的开发方式一样,而二次开发者只需要拷贝业务模块文件夹再做细节修改了。其实这样的开发方式仅仅是减少了开发者在多个文件夹来回切换的耗时,他们还是需要梳理模块内部逻辑,并且需要在顶层Store中添加数据关注。除非我们使用更多的Props使得组件可以满足各种场景,开发者只需要传递相关属性,即可直接使用,这样就会使得我们的业务组件非常的重,有相当多作为判断用的鸡肋般的代码。React Hooks不了解React Hooks的同学可以先移步React Hooks的简单介绍Hooks的实质是把面向生命周期编程变成了面向业务逻辑编程。此时我们业务组件的封装方式可以修改成Hooks + UI Component。下面使用「排行榜」复杂业务模块的封装来进行实例说明。1、Hooks逻辑import React, { useEffect, useState } from ‘react’import _ from ‘axios’function useRank (cgi, params) { const [rankList, setRankList] = useState([]) const [myRank, setMyRank] = useState({}) const [isEnd, setIsEnd] = useState(0) // 第二个参数传递 [] 相当于将effect作为class Component中的componentDidMount使用 useEffect(() => { let query = ’’ Object.keys(params).forEach((key, idx) => { query += idx === 0 ? ?${key}=${params[key]} : &amp;${key}=${params[key]} }) // 拉取逻辑 _.get(${cgi}${query}) .then(res => { const { myRank, rankList, isEnd } = camelcase(res.data.result) setRank(rankList) setMyRank(myRank) setIsEnd(isEnd) }) .catch(e => console.log(e)) }, []) return { myRank, rankList, isEnd }}2、UI Componentimport React from ‘react’import { useRank } from ‘./hooks’const Rank = ({ cgi = ’’ params = { off_set: 0, page_size: 10 },}) => { // 使用自定义Hook const { rank = [], myRank, isEnd } = useRank(cgi, params) return ( <div> … </div> )}export default Rank按这种方式我们可以在需要拉取rank数据的时候直接调用方法获取到,并且不同组件中数据相互独立,非常适用于多榜单切换的情况,如下图const { rank = [], myRank, isEnd } = useRank(cgi, params)业界其他方式具体参考React Hooks深入不浅出感谢阅读,祝大家新年快乐~~~~参考React Hooks的简单介绍React Hooks深入不浅出如何更优雅地使用 Redux