2019-08-14 React HOC
- 最近在项目中,组件中嵌套层级太深,传参太麻烦。在思考有没有更简单的办法。想到React中有一个HOC函数(high order components)。
- react最近也release了一个新属性 hooks新属性
- 希望想到的两个点有帮助
- 1.先看看HOC
最近在项目中,组件中嵌套层级太深,传参太麻烦。在思考有没有更简单的办法。想到React中有一个HOC函数(high order components)。
react最近也release了一个新属性 hooks新属性
希望想到的两个点有帮助
1.先看看HOC
第一步,当然是去官方文档查看相关资料
1
2
3
4
1.1为什么会有HOC
使用hoc的目的是高效的重复利用组件
2.2什么是HOC
HOC就是传入一个组件,返回一个新组件
PS:官方文档的原话是take a component and return a new component
1
2
3
4
5
6
const EnhancedComponent = hoc(OriginalComponent);
import { withFunctions } from 'my-module';
class OriginalComponent extends React.Component {
...
}
export default withFunctions(OriginalComponent);
1
2
3
4
5
6
7
8
9
10
export function withFunctions(OriginalComponent) {
return class extends React.Component {
// make some enhancements
...
render() {
//return original component with additional props
return <OriginalComponent {...this.props} />
}
}
}
你可以定义,引用其他方法一样,来使用HOC
1
2
3
4
5
6
7
// src/hoc/index.js
import React from 'react';
export function withFunctions(WrappedComponent) {
return class extends React.Component {
...
}
}
1
2
// src/components/OriginalComponent.js
import { withFunctions } from '../hoc';
在刚学习react,和在使用react的过程中,这篇文章至少看过两遍。都不是很懂。 如今react也写了快两年了,再次看,带着疑问,目的去看,比之前更清晰。
在平常的项目中,引入外面库的时候,经常使用HOC,最常用的是,connect 平常项目中的用法是,
1
export default connect(mapStateToProps,mapDispatchToProps)(ComponentApp)
第二步,动动小手,依据官方文档,写个例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// App.js
import { DataSource } from './util';
import { CommentListWithSubscription } from './CommentList';
import { BlogPostWithSubscription } from './BlogPost';
class App extends Component {
render() {
return (
<div>
<CommentListWithSubscription />
<BlogPostWithSubscription />
</div>
);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// BlogPost.js
import React from 'react';
import { DataSource } from './util';
import { withSubscription } from './HOC';
import { List } from 'antd';
class BlogPost extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
blogPost: DataSource.getBlogPost(props.id)
};
}
componentDidMount() {
DataSource.addChangeListener(this.handleChange);
}
componentWillUnmount() {
DataSource.removeChangeListener(this.handleChange);
}
handleChange() {
this.setState({
blogPost: DataSource.getBlogPost(this.props.id)
});
}
render() {
return <List
header={<div>blogPost</div>}
footer={<div>blogPost</div>}
bordered
dataSource={this.state.blogPost}
renderItem={blogPost => (
<List.Item>
<div key={blogPost.id}>{blogPost.content}</div>
</List.Item>
)}
/>
;
}
}
export const BlogPostWithSubscription = withSubscription(
BlogPost,
(DataSource, props) => DataSource.getBlogPost(props.id)
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// CommentList.js
import React from 'react';
import { DataSource } from './util';
import { withSubscription } from './HOC';
import { List } from 'antd';
class CommentList extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
// "DataSource" is some global data source
comments: DataSource.getComments()
};
}
componentDidMount() {
// Subscribe to changes
DataSource.addChangeListener(this.handleChange);
}
componentWillUnmount() {
// Clean up listener
DataSource.removeChangeListener(this.handleChange);
}
handleChange() {
// Update component state whenever the data source changes
this.setState({
comments: DataSource.getComments()
});
}
render() {
return (
<List
header={<div>Comment</div>}
footer={<div>Comment</div>}
bordered
dataSource={this.state.comments}
renderItem={comment => (
<List.Item>
<div key={comment.id}>{comment.content}</div>
</List.Item>
)}
/>
);
}
}
export const CommentListWithSubscription = withSubscription(
CommentList,
(DataSource) => DataSource.getComments()
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// util.js
export const DataSource = {
getComments: () => {
return [
{id: 1, content: 'prefilerate'},
{id: 2, content: 'lead to'},
{id: 3, content: 'be responsible for'},
{id: 4, content: 'contribute to'},
{id: 5, content: 'enormous'},
{id: 6, content: 'notation'}
]
},
getBlogPost: (id) => {
return [
{id: 1, content: 'prefilerate'},
{id: 2, content: 'lead to'},
{id: 3, content: 'be responsible for'},
{id: 4, content: 'contribute to'},
{id: 5, content: 'enormous'},
{id: 6, content: 'notation'}
]
},
addChangeListener: (func) => {
func()
},
removeChangeListener: (func) => {
func()
},
}
以上,还需要在项目中多实践,应用,思考。
This post is licensed under CC BY 4.0 by the author.