写在前面
高阶组件简称为 HOC,即 High Order Component ,是 React 中,高阶组件是一个函数,其接收的参数为一个组件,并返回一个组件。
1. 为什么使用 HOC
为什么使用 HOC,简单来说,就是为了减少代码的重复。但是这种减少代码重复的方式是通过代码逻辑的复用实现的。
组件化思想就是减少代码重复的一种方式,对象的继承思想也是减少代码重复的一种方式。
HOC 是在组件化的基础上进行更进一步的代码复用,因为在各组件之间可能会使用相同的代码逻辑,将这些相同的代码逻辑抽离出来,放到高阶组件中进行复用。
2. 如何使用 HOC
在了解了 HOC 的诞生原因后,那么应该如何使用 HOC 呢?请时刻牢记一句话:HOC 本身是一个接收组件为参数并返回一个新组件的函数,不是一个组件
那么我们知道 HOC 是返回一个新组件,因此在 HOC 函数内肯定有 return new Component 的语句,那么旧的组件如何和新组件产生关联呢?答案就是在新组件中使用旧组件。
假如组件 A 和组件 B 都有读取浏览器本地存储中 test 属性值的需求,为了实现读取本地存储数据代码的复用,下面就创建一个简单的 HOC 高阶组件。
index.js
localStorage.setItem('test', '我是 test')
withTest.js
import React, {useState} from 'react';
function withTest(OldComponent) {
return function (props) {
const [test, setTest] = useState(localStorage.getItem('test'))
return (
<OldComponent test={test} {...props}/>
)
}
}
export default withTest
A.js
import React from 'react';
import withTest from './withTest';
function A(props) {
return (
<div>
我是 A 组件
我拿到的 test 为:{props.test}
</div>
)
}
export default withTest(A)
B.js
import React from 'react';
import withTest from './withTest';
function B(props) {
return (
<div>
我是 B 组件
我拿到的 test 为:{props.test}
</div>
)
}
export default withTest(B)
App.js
import React from 'react';
import WithTestA from './A';
import WithTestB from './B'
function App() {
return (
<div className="App">
我是APP
<WithTestA/>
<WithTestB/>
</div>
);
}
export default App;
可以看到,在 HOC 高阶组件中,复用的代码逻辑是定义在新创建的组件中的,新组件中使用旧组件作为子组件时,通过 prop 的方式传递给子组件,子组件就可以拿到对应的数据。
我们在使用时也是使用的 HOC 返回后的新组件,新组件是包含了代码逻辑的旧组件。因此新组件就是包裹着旧组件的一个容器,这个容器中有对应的代码逻辑,其得到的数据通过 prop 的方式传递为旧组件。
3. HOC 带参数
HOC 是一个函数,除了可以接收一个组件外,当然可以接收其他的数据,接收的数据也可以传递给旧组件,如下
withTest.js
import React, {useState} from 'react';
function withTest(OldComponent, args) {
return function (props) {
const [test, setTest] = useState(localStorage.getItem('test'))
return (
<OldComponent test={test} {...props} args={args}/>
)
}
}
export default withTest
A.js
import React from 'react';
import withTest from './withTest';
function A(props) {
return (
<div>
我是 A 组件
我拿到的 test 为:{props.test}
我拿到的 args 为:{props.args}
</div>
)
}
export default withTest(A, 'a')
4. connect 将参数抽离
connect 是一个返回高阶组件的高阶函数!
React-Redux 中的 connect 函数采用的方式是将 HOC 做成一个 Component => Component 的单参数 HOC,将从函数传参过来的数据传递到了第一层的函数中。
单参数 HOC 的好处就是便于组合 compose 到一起。