react高阶组件

1,828 阅读3分钟

高阶组件不是组件,而是一个普通的函数,传入一个组件,返回一个新的组件。

构想一个使用场景(留言板):

昵称和手机号可以不改变,内容改变。

1.高阶组件的实现

import React,{Component} from 'react';
import ReactDOM from 'react-dom';
import UserName from './UserName';
import Mobile from './Mobile';
 export default class Memo extends Component{
     render(){
         return (
             <form>
                  <UserName/>
                  <Mobile/>
                  留言 <textarea></textarea>  
             </form>
         )
     }
 }

当填写用户名和手机号后刷新页面,用户名和手机号依然存在。实现:将这两个值保存到localstorage中,刷新后重新加载。

username组件

import React,{Component} from 'react';
class UserName extends Component{
    componentDidMount(){
        this.username.value=localStorage.getItem('username')||'请输入昵称';
    }
    handleChange=(event)=>{
        localStorage.setItem('username',event.target.values())
    }
    render(){
        return <label>用户名<input ref={input=>this.username=input} onChange={this.handleChange}  /><br/></label>
    }
}
export default UserName;

1.如果还需要手机号,qq号等和username组件有相同逻辑的组件,会造成代码重复。 2.如果要改变这套逻辑,所有的组件都要修改。

这时需要用到高阶组件去复用相同的逻辑:

高阶组件就是一个函数,用来封装重复的逻辑。
传进去一个老组件,返回一个新组件

高阶组件

import React,{Component} from 'react';
export default function(OldComponent,name,placeholder){
      class NewComponent extends Component{
        constructor(){
            super();
            this.state = {data:''};
        }  
        componentWillMount(){
            this.setState({data:localStorage.getItem(name)||placeholder});
        }
        save=(event)=>{
            localStorage.setItem(name,event.target.values())
        }
        render(){
            return <OldComponent data={this.state.data} save={this.save}/>
        }
      }
      return NewComponent;
}

改造username组件

import React,{Component} from 'react';
import local from './local';
class UserName extends Component{
    render(){
        return <label>用户名<input defaultValue={this.props.data}  onChange={this.props.save}/><br/></label>
    }
}
export default local(UserName,'username','用户名');

Mobile组件

import React,{Component} from 'react';
import local from './local';
class Mobile extends Component{
    render(){
        return <label>手机号<input defaultValue={this.props.data}  onChange={this.props.save}/><br/></label>
    }
}
export default local(Mobile,'mobile','手机号');

这样就可以实现组件逻辑的封装。

2.增加需求,再次改造高阶组件

如果高阶组件的数据通过fetch从后台获取。需要怎样修改。

fetch高阶组件

import React,{Component} from 'react';
export default function(OldComponent,name,placeholder){
      class NewComponent extends Component{
        constructor(){
            super();
            this.state = {data:''};
        }  
        componentWillMount(){
            fetch('/user.json').then(response=>response.json()).then(user=>{
                this.setState({data:user[name]||placeholder});
            });
           
        }
        save=(event)=>{
            localStorage.setItem(name,event.target.values())
        }
        render(){
            return <OldComponent data={this.state.data}  />
        }
      }
      return NewComponent;
}

user.json

{
    "username": "xxxxxx",
    "mobile": "15711111111"
}

3.高阶组件中的值从localhost和fetch共同获取

如果想通过locahost获取username的值:xx。再使用xx从后台获取数据。

username -> xx -> 张三

为了简化省略save方法,localstorage中已经有了username:xx。着重看一下逻辑。

user.json

{
    "xx": "张三",
    "mobile": "15711111111"
}

Username组件

import React,{Component} from 'react';
import ajax from './ajax';
import local from './local';
class UserName extends Component{
    render(){
        return <label>用户名<input value={this.props.data}  /><br/></label>
    }
}
UserName = ajax(UserName,'username','用户名');
UserName = local(UserName,'username','用户名');
export default UserName;

Ajax高阶组件

import React,{Component} from 'react';
export default function(OldComponent){
      class NewComponent extends Component{
        constructor(){
            super();
            this.state = {data:''};
        }  
        componentWillMount(){
            fetch('/user.json').then(response=>response.json()).then(user=>{
                this.setState({data:user[this.props.data]});
            });
           
        }
        render(){
            return <OldComponent data={this.state.data}  />
        }
      }
      return NewComponent;
}

local高阶组件

import React,{Component} from 'react';
export default function(OldComponent,name,placeholder){
      class NewComponent extends Component{
        constructor(){
            super();
            this.state = {data:''};
        }  
        componentWillMount(){
            this.setState({data:localStorage.getItem(name)||placeholder});
        }
        render(){
            return <OldComponent data={this.state.data} />
        }
      }
      return NewComponent;
}

为什么ajax方法要在local方法上呢?(着重注意)

UserName = ajax(UserName,'username','用户名');
UserName = local(UserName,'username','用户名');

因为这是组件的封装:先使用ajax封装,然后用local封装。等到组件渲染的时候,就是从外向内执行,先执行local,从localstorage中获取到xx。然后通过ajax,使用xx在json文件中获取数据。