十、高阶组件使用场景
- 操纵props
在被包装组件接收props前,高阶组件可以先拦截到props,对props执行增加、删除或修改的操作,然后将处理后的props再传递给被包装组件,上一篇的例子就属于这种情况。
- 通过ref访问组件实例
import Todo from "./components/Todo"; function App(props) { let todoElm = null; return ( <div className="todoapp stack-large"> <Todo ref={(el) => { todoElm = el; }} /> <button onClick={() => todoElm.someMethod()}>点击</button> </div> ); } export default App;
function withPersistentData(WrappedComponent) { return class extends Component { componentWillMount() { // let data = localStorage.getItem('data'); this.setState({ data: 11 }); } someMethod() { this.wrappedInstance.someMethodInWrappedComponent(); } render() { //this.props是WrappedComponent的props,data也将是WrappedComponent的props return <WrappedComponent ref={(instance) => { this.wrappedInstance = instance }} data={this.state.data} {...this.props} /> } } } //被包装的组件 class MyComponent extends Component { constructor(props) { super(props); this.someMethodInWrappedComponent = this.someMethodInWrappedComponent.bind(this); } someMethodInWrappedComponent(){ console.log(1); } render() { return ( <div> data:{this.props.data} </div> ) } } const Todo = withPersistentData(MyComponent) export default Todo;
高阶组件通过this.wrappedInstance保存WrappedComponent实例的引用,在someMethod中,通过this.wrappedInstance调用WrappedComponent中的方法。
- 组件状态提升
高阶组件可以通过 将被包装组件的状态及相应的状态处理方法提升到高阶组件自身内部,从而实现被包装组件的无状态化(无状态组件更容易被复用)。
function withPersistentData(WrappedComponent) { return class extends Component { constructor(props) { super(props); this.state = { value: '' } this.handleValueChange = this.handleValueChange.bind(this); } handleValueChange(event) { this.setState({ value: event.target.value }) } render() { const newProps = { controlledProps: { value: this.state.value, onChange: this.handleValueChange } } return <WrappedComponent {...this.props} {...newProps} /> } } } class SimpleControlledComponent extends Component { render() { return ( <input name="simple" {...this.props.controlledProps}/> ) } } const Todo = withPersistentData(SimpleControlledComponent) export default Todo;
这个例子把受控组件value属性用到的状态和处理value变化的回调函数都提升到高阶组件中。SimpleControlledComponent变成无状态组件,状态由高阶组件维护。
- 用其他元素包装组件
常用于为WrappedComponent增加布局或修改样式
function withPersistentData(WrappedComponent) { return class extends Component { render() { return ( <div style={{background: 'red'}}> <WrappedComponent {...this.props} /> </div> ) } } }