一、引言
通过这周需要的开发,我发现自己在编写代码的过程中不太关注代码的复用性和可维护性,不经意间就间接简略的复制粘贴就完事,这样看起来是实现了性能,然而却为当前的开发留下了很大的隐患。所以,这周我顺便联合了本人开发过程中的问题,简略了理解了一下对于进步 React 代码复用性的两种办法。
二、应用 React 高阶组件来晋升代码的可复用性
先介绍一下什么是 React 的高阶组件,
高阶组件是一个函数,接管一个组件,而后返回一个新的组件。
const EnhancedComponent = highOrderComponent(WrappedComponent);
要记住的是,尽管名称是 高阶组件 ,然而高阶组件不是组件,而是 函数!
既然是函数,那就能够有参数,有返回值。从下面能够看出,这个函数接管一个组件 WrappedComponent 作为参数,返回 加工过 的新组件 EnhancedComponent。其实高阶组件就是设计模式里的装璜者模式。
能够说,组件是把 props 转化成 UI,而 高阶组件是把一个组件转化成另外一个组件。
上面是一个简略的高阶组件:
import React, {Component} from 'react';
export default (WrappedComponent) => {
return class EnhancedComponent extends Component {
// do something
render() {return <WrappedComponent />; //HOC 返回的是一个新的组件}
}
}
其实,这只是其中的一种高阶组件,这个时候 高阶组件复用的是组件,也就是说在一个通用的组件中增加额定的逻辑,而后返回一个增加了额定办法和参数的新组件。
另外一种高阶组件 复用的是多个组件中雷同的逻辑,返回一个新的组件。我在开发中应用到的就是这种模式的高阶组件。它是这样的模式:
// 组件一
class Component1 extends React.Component {...}
// 组件二
class Component2 extends React.Component {...}
// 假如组件一和组件二都须要应用雷同的函数 foo
// 设计一个能够复用 foo 的高阶组件
const HOCComponent = (Component, props) => {
const obj = {foo1() {},
foo2() {},
... // 这里示意想增加的其余参数
};
const newprops = Object.assign({}, obj, props);
return <Component {...newprops}/>
}
// 应用该高阶组件
let newComponent1 = HOCComponent(Component1, this.props);
let newComponent2 = HOCComponent(Component2, this.props);
这样就能够实现复用两个组件雷同的函数或者其余的参数了,不必在每个组件中都写反复的代码。
三、应用 React Hook:useState()来晋升代码的可复用性
先简略介绍一下 useState 这个 hook,
用法:
const [state, setState] = useState(initialState);
返回值:state,更新 state 的函数 setState
参数:初始的 state:initialState
因为 useState 这个 Hook 诞生之前,如果想应用 state 必须得定义类组件,函数组件无奈应用 state,然而组件的演变必定是往轻量化这个方向演变的,所以 useState 就能够是函数组件也能够应用 state。
来看一下上面这个例子:
有一个这样的场景:
当初有 小 A,小 B 两位同学,每位同学都处于未穿鞋的状态,小 A 穿鞋须要 2s,小 B 穿鞋须要 5s,在页面一中用文字描述两位同学的穿鞋状态变更(如果小 A 正在穿鞋中,则在页面上显示 ‘ 小 A 正在穿鞋子 ’,如果小 A 曾经穿好了鞋子,则将文字替换为 ‘ 小 A 曾经穿好鞋子 ’)
应用 class 组件实现是这样的:
import React from "react";
class Page extends React.Component {
state = {
data: [{ id: 1, name: "小 A", time: "2000"},
{id: 2, name: "小 B", time: "5000"}
]
};
start(item) {
this.setState({[item.id]: "穿鞋子"
});
setTimeout(() => {
this.setState({[item.id]: "穿好鞋子"
});
}, item.time);
}
componentDidMount() {
this.state.data.forEach(item => {this.start(item);
});
}
render() {
return (
<div>
{this.state.data.map(item => {
return (<h1 key={item.id}>
{this.state[item.id] === "穿鞋子"
? `${item.name}正在穿鞋子...`
: `${item.name}曾经穿好鞋子了 `}
</h1>
);
})}
</div>
);
}
}
export default Page;
应用 Hook 组件实现是这样的:
自定义 Hook 如下:
- src/useHook.js
import React, {useState} from "react";
function useHook(item) {const [status, setStatus] = useState("穿鞋子");
setTimeout(() => {setStatus("穿好鞋子");
}, item.time);
return (<h1 key={item.id}>
{status === "穿鞋子"
? `${item.name}正在穿鞋子...`
: `${item.name}曾经穿好鞋子了 `}
</h1>
);
}
export default useHook;
援用 hook 的函数组件
- src/hookDemo1.js
import React from "react";
import useHook from "./useHook";
function Page() {
const data = [{ id: 1, name: "小 A", time: "2000"},
{id: 2, name: "小 B", time: "5000"}
];
return (
<div>
{data.map(item => {return useHook(item);
})}
</div>
);
}
export default Page;
看起来并没有什么区别嘛,代码量也没有缩小。
然而,如果小 C 和小 D 也要实现这样的形容,应用定义好的 Hook 就简略多了。
- src/hookDemo2.js
import React from "react";
import useHook from "./useHook";
function Page() {
const data = [{ id: 1, name: "小 C", time: "4000"},
{id: 2, name: "小 D", time: "8000"}
];
return (<div style={{ color: "lightblue"}}>
{data.map(item => {return useHook(item);
})}
</div>
);
}
export default Page;