React-JS:通过HOC包装器访问子方法

时间:2016-06-27 20:39:26

标签: javascript reactjs redux react-redux

我有一个Editor组件,如下所示:

class EditorComp extends Component {
  focus() {
    this.refs.input.focus();
  }

  render() {
    return (
      <input 
        ref="input"
        ...
      />
    );
  }
}

因此,使用EditorComp的元素可以设置ref并调用其focus方法并将焦点应用于较低级别的输入,如下所示:

class Parent extends Component {
  render() {
    return (
      <div>
        <button onClick={() => this.refs.editor.focus()}>Focus</button>
        <EditorComp ref="editor" />
      </div>
    );
  }
}

但是,当将EditorComp包裹在高阶组件中时(如react-redux的{​​{1}})connect()会丢失焦点方法,因为它会被困在HOC下面。

示例:

EditorComp

有没有办法通过子组件的父HOC传递方法或组件引用?

编辑:或者是否有一个反向解决方案,其中父母放下一个设置焦点命令的功能?我考虑使用const WrappedEditor = connect()(EditorComp); // react-redux's connect, for example const wrappedEditorInstance = <WrappedEditor />; wrappedEditorInstance.focus() // Error! Focus is not a function. ,并让孩子听父母打电话给event-emitter事件,但这似乎不实用且不必要。

1 个答案:

答案 0 :(得分:7)

1路返回comp实例

class EditorComp extends Component {
  focus() {
    this.refs.input.focus();
  }
  componentDidMount(){
    this.props.onMount(this)
  }
  render() {
    return (
      <input
        ref="input"
        ...
      />
    );
  }
}
export default connect(state=>({state}), actions)(EditorComp);


class Parent extends Component {
  render() {
    return (
      <div>
        <button onClick={() => this.editor.focus()}>Focus</button>
        <EditorComp  onMount={c=>this.editor=c}  ref="editor" />
      </div>
    );
  }
}

2路传递位置

class EditorComp extends Component {
  componentDidUpdate(prevProps, prevState){
    let {input}= this.refs
    this.props.isFocus? input.focus():input.blur();
  }
  render() {
    return (
      <input
        ref="input"
        ...
      />
    );
  }
}
export default connect(state=>({state}), actions)(EditorComp);


class Parent extends Component {
  render() {
    return (
      <div>
        <button onClick={() => this.setState({isfocus:true});}>Focus</button>
        <EditorComp  isFocus={this.state.isfocus}  ref="editor" />
      </div>
    );
  }
}