MKeller MKeller - 3 months ago 29
React JSX Question

React ES6 | How to access child component functions via refs

The docs for React state that component functions can be accessed by a parent component via refs. See: https://facebook.github.io/react/tips/expose-component-functions.html

I am attempting to use this in my application but run into an "undefined is not a function" error when the child function is called. I'm wondering if this has anything to do with using the ES6 format for React classes because I don't see any other differences between my code and the docs.

I have a Dialog component that looks like the following pseudocode. The Dialog has a "Save" button that calls save(), which needs to call the save() function in the child Content component. The Content component collects information from child form fields and performs the save.

class MyDialog extends React.Component {
save() {
this.refs.content.save(); <-- save() is undefined
}

render() {
return (
<Dialog action={this.save.bind(this)}>
<Content ref="content"/>
</Dialog>);
}
}

class Content extends React.Component {
save() {
// Get values from child fields
// and save the content
}
}


I could instead pass a prop (saveOnNextUpdate) down to Content and then execute save whenever it is true, but I would rather figure out how to get the method detailed in the React doc above to work.

Any ideas on how to get the doc approach to work or access the child component function in a different way?

Answer

As it turns out, m90 was right -- this was a different issue entirely. I'm posting the solution in case someone runs into the same problem in the future.

My application is built with Redux, and the problem stems from using the react-redux connect function to connect a component to the store/global state. For some reason, exporting a component and connecting it to the store makes it impossible to access the functions inside of it. In order to get around this, I had to remove all use of global state from Content so that I could export it as a "dumb" component.

To be more clear, Content.js looked like this:

var connect = require('react-redux').connect;

class Content extends React.Component {
  save() {
    // Get values from child fields
    // and save the content

    // Use of this.props.stateObject
  }
}

function mapStateToProps(state) {
  const {
    stateObject
  } = state;

  return {
    stateObject
  };
}

module.exports = connect(mapStateToProps)(Content);

Removing the use of global state (and therefore the use of connect and mapStateToProps allowed me to export the component using:

module.exports = Content;

Accessing this.refs.content.save() magically worked after doing this.

Comments