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

React-JS: Access a child's method through HOC wrapper

我有一个 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-reduxconnect()),EditorComp 会失去焦点方法,因为它被困在HOC.

示例:

const WrappedEditor = connect()(EditorComp); // react-redux's connect, for example
const wrappedEditorInstance = <WrappedEditor />;

wrappedEditorInstance.focus() // Error! Focus is not a function.

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


编辑:或者是否有一个反向解决方案,其中 parent 传递一个设置焦点命令的函数?我考虑过使用 event-emitter,并让 child 监听 parent 调用的 focus 事件,但这似乎很笨拙且没有必要。

1 路 return 补偿实例

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>
    );
  }
}