首页 > 解决方案 > React context consumer how to access ref on to the consuming component

问题描述

I've build a higher order component using the new context API of React and I am trying to to find a way to be able to access the reference (via ref()) of a wrapped child component.

tl/dr: Essentially I want to forward the ref from the Consumer to the actual component.

Here's a specific example. The RootComponent sets the value for the CoolProvider that is suppose to be exposed on all wrapped child components. A child component is wrapped using withCool() such that it can access props.cool. (Of course in a real world example everything is much more complex and there are dozens of components.)

Now independent of knowing whether a child component has been wrapped I would like to be able to get a reference to it via ref() as illustrated in RootComponent but unfortunately the wrapped components do not support ref() anymore as they are functional!

Check out this live demo (https://jsfiddle.net/64t0oenz/3/) and inspect the web console. You will see that only the callback for the non-wrapped component fires.

My question is: is there a way to forward the reference request from the CoolConsumer to the actual component such that the parent component can access it's reference?

const { Provider: CoolProvider, Consumer: CoolConsumer } = React.createContext();

const withCool = Component => props => (
  <CoolConsumer>
    {cool => <Component {...props} cool={cool} />}
  </CoolConsumer>
);

class ChildComponent extends React.Component {
  render() {
    return this.props.cool ? (
        <div>Isn't this cool?</div>
    ) : (
      <div>Not so cool!</div>
    );
  }
}

const CoolChildComponent = withCool(ChildComponent);

class RootComponent extends React.Component {
  render() {
    return (
        <CoolProvider value={true}>
        <ChildComponent ref={(c) => { console.log('Normal child ref', c); }}/>
        <CoolChildComponent ref={(c) => { console.log('Cool child ref', c); }}/>
      </CoolProvider>
    );
  }
}

ReactDOM.render(<RootComponent />, document.querySelector('#cool'));

标签: javascriptreactjs

解决方案


我想到了!使用 React 的forwardRefAPI 可以完全实现我想要的。唯一需要的改变是更换

const withCool = Component => props => (
  <CoolConsumer>
    {cool => <Component {...props} cool={cool} />}
  </CoolConsumer>
);

const withCool = Component => React.forwardRef((props, ref) => (
  <CoolConsumer>
    {cool => <Component {...props} cool={cool} ref={ref} />}
  </CoolConsumer>
));

这是修改后的现场演示:https ://jsfiddle.net/64t0oenz/4/ 打开开发控制台,您现在将看到 2 个控制台日志打印对正常和酷组件的引用。


推荐阅读