1. 什么是高阶组件?
- 高阶组件就是一个函数,它接受另一个组件作为参数,并返回一个新的组件。
- 当 React 组件被包裹时(warped),高阶组件会返回一个增强的 React 组件。
- 高阶组件让代码更具有复用性、逻辑性和抽象特性。
2. 为什么要用高阶组件?
- 在不用高阶组件的情况下,写两个普通的组件
Welcome
和 Goodbye
,它们都从 localStorage
中读取 userName
,然后对 userName
做一些处理。 Welcome
组件:
import React, {Component} from 'react'
class Welcome extends Component {
constructor(props) {
super(props);
this.state = {
username: ''
}
}
componentWillMount() {
let username = localStorage.getItem('username');
this.setState({
username: username
})
}
render() {
return (
<div>welcome {this.state.username}</div>
)
}
}
export default Welcome;
import React, {Component} from 'react'
class Goodbye extends Component {
constructor(props) {
super(props);
this.state = {
username: ''
}
}
componentWillMount() {
let username = localStorage.getItem('username');
this.setState({
username: username
})
}
render() {
return (
<div>goodbye {this.state.username}</div>
)
}
}
export default Goodbye;
- 可以发现, 两个组件的大部分代码都是重复的,这种代码冗余非常不好。
3. 怎么写高阶组件?
- 我们可以将两个组件进行抽象,提取公共部分,在公共部分中读取
userName
, 并将 userName
传递给具体的组件。改写如下:
import React, {Component} from 'react'
export default (WrappedComponent) => {
class WrapWithUsername extends Component {
constructor() {
super();
this.state = {
username: ''
}
}
componentWillMount() {
let username = localStorage.getItem('username');
this.setState({
username: username
})
}
render() {
return <WrappedComponent username={this.state.username}/>
}
}
return WrapWithUsername;
}
- 上面的
WrapWithUsername
就是一个抽象的高阶组件,它接受另一个组件作为参数,并返回一个新的组件。高阶组件可以对原始组件(传入组件)进行修饰,这样在保持单个组件封装性的同时还保留了易用性。 - 使用上面的高阶组件来简化
Welcome
和 Goodbye
组件:
import React, {Component} from 'react';
import wrapWithUsername from 'wrapWithUsername';
class Welcome extends Component {
render() {
return (
<div>welcome {this.props.username}</div>
)
}
}
Welcome = wrapWithUsername(Welcome);
export default Welcome;
import React, {Component} from 'react';
import wrapWithUsername from 'wrapWithUsername';
class Goodbye extends Component {
render() {
return (
<div>goodbye {this.props.username}</div>
)
}
}
Goodbye = wrapWithUsername(Goodbye);
export default Goodbye;
- 可以看出,高阶组件通过
props
把 username
传递给目标组件,目标组件只管从 props 拿来用就好了,而不需要关心 username 是怎么来的。