助你完全理解React高阶组件(Higher-Order Components)
原文地址:https://github.com/brickspert... (如果你觉得对你有帮助,请在github给个star~您的start是我不断创作的动力!)
原文不断更新,此处不维护。
有时候人们很喜欢造一些名字很吓人的名词,让人一听这个名词就觉得自己不可能学会,从而让人望而却步。但是其实这些名词背后所代表的东西其实很简单。来自React.js 小书
高阶组件定义
a higher-order component is a function that takes a component and returns a new component.
翻译:高阶组件就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件。
理解了吗?看了定义似懂非懂?继续往下看。
函数模拟高阶组件
我们通过普通函数来理解什么是高阶组件哦~
- function welcome() {
- let username = localStorage.getItem('username');
- console.log('welcome ' + username);
- }
- function goodbey() {
- let username = localStorage.getItem('username');
- console.log('goodbey ' + username);
- }
- welcome();
- goodbey();
- function welcome(username) {
- console.log('welcome ' + username);
- }
- function goodbey(username) {
- console.log('goodbey ' + username);
- }
- function wrapWithUsername(wrappedFunc) {
- let newFunc = () => {
- let username = localStorage.getItem('username');
- wrappedFunc(username);
- };
- return newFunc;
- }
- welcome = wrapWithUsername(welcome);
- goodbey = wrapWithUsername(goodbey);
- welcome();
- welcome();
好了,我们里面的wrapWithUsername
函数就是一个“高阶函数”。
他做了什么?他帮我们处理了username
,传递给目标函数。我们调用最终的函数welcome
的时候,根本不用关心username
是怎么来的。
- function study(username){
- console.log(username+' study');
- }
- study = wrapWithUsername(study);
- study();
这里你是不是理解了为什么说wrapWithUsername
是高阶函数?我们只需要知道,用wrapWithUsername
包装我们的study
函数后,study
函数第一个参数是username
。
我们写平时写代码的时候,不用关心wrapWithUsername
内部是如何实现的。
高阶组件
高阶组件就是一个没有副作用的纯函数。
我们把上一节的函数统统改成react
组件。
最普通的组件哦。
welcome
函数转为react
组件。
- 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;
goodbey
函数转为react
组件。
- 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;
现在你是不是更能看到问题所在了?两个组件大部分代码都是重复的唉。
按照上一节wrapWithUsername
函数的思路,我们来写一个高阶组件(高阶组件就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件)。
- import React,{Component} from 'react'
- export default (WrappedComponent) => {
- class NewComponent 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 NewComponent
- }
这样我们就能简化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;
看到没有,高阶组件就是把username
通过props
传递给目标组件了。目标组件只管从props
里面拿来用就好了。
到这里位置,高阶组件就讲完了。你再返回去理解下定义,是不是豁然开朗~
你现在理解react-redux
的connect
函数~
把redux
的state
和action
创建函数,通过props
注入给了Component
。
你在目标组件Component
里面可以直接用this.props
去调用redux state
和action
创建函数了。
- ConnectedComment = connect(mapStateToProps,mapDispatchToProps)(Component);
相当于这样
antd
的Form也是一样的
- const WrappedNormalLoginForm = Form.create()(NormalLoginForm);
参考地址: