Justin Schultz Justin Schultz - 3 months ago 22
React JSX Question

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

I have an

Editor
component that looks like so:

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

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


So that elements that use
EditorComp
can set a ref and call its
focus
method and apply focus to the lower level input, like so:

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


However, when wrapping
EditorComp
in a Higher Order Component (like
react-redux
's
connect()
) the
EditorComp
loses the focus method because it gets trapped underneath the HOC.

Example:

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

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


Is there a way to pass up method or component references through the parent HOCs of a child component?




Edit: Or is there a reverse solution in which the parent hands down a function which sets the focus command? I've considered using an
event-emitter
, and having the child listen to a
focus
event called by the parent, however this seems unwieldy and unnecessary.

Answer

1 way return comp instance

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 way pass down position

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