2

I am using React and Apollo for my project.

I got this in my component MenuModal:

onClick = () => {
    console.log(this.child)
    this.child.onSubmit(); // do stuff
};

render() {
    return (
        <Modal.Content scrolling>
            <MenuEdit
                ref={ref => (this.child = ref)} // Using ref to access it's properties
                selectedValues={selectedValues}
                match={match}
                menu={menu}
            />

My component MenuEdit has a function defined in class:

onSubmit = values => {
    console.log('calling inner form submit', values);
    if (this.child) {
        this.child.submitFromOutside();
    }
};

I should be able to call onSubmit from MenuModal right?

But I am currently getting this: enter image description here

And when I console.log this.child in my onClick function I can see this:

enter image description here So there's no onSubmit function there. When seeing GraphQL I wondered if it had something to do with me exporting the component with the graphQL HOC.

export default compose(
    graphql(UPDATE_MENU, { name: 'updateMenu' }),
    withApollo,
    withRouter
)(MenuEdit);

And when I changed it just to:

export default MenuEdit;

I can see my function enter image description here

So I wonder how I write my export so I still can access my function in my child. Thanks.

Martin Nordström
  • 5,779
  • 11
  • 30
  • 64

2 Answers2

0

The HOC wrapps your component into another component. You can see this in the React devtools. You will see that the component renders a component around your wrapped component. Something like this

<Apollo(ChildComponent)>
  <ChildComponent />
</Apollo>

Your ref then points to the Apollo(ChildComponen) element instance.

What you are doing here looks like an antipattern to me. In React we usually don't call functions on rendered elements (except sometimes DOM elements). The idea is rather that children call functions of their parents by receiving them as properties. The best thing in your case is to get rid of the reference and move your state and actions up the component chain. Alternatively you can use the new render prop style in react-apollo.

Herku
  • 7,198
  • 27
  • 36
0

There was a contribution to the Apollo repository to address this issue... https://github.com/apollographql/react-apollo/pull/410

Wrapping your component export like this withApollo(Component, { withRef: true }) will expose your child methods. Accessible using ref.current.wrappedInstance.

Luke
  • 36
  • 6