5

I would like to call a method from a child component, as per suggested here Call child method from parent

However, it doesn't work when the child component is wrapped with connect from react-redux as in the example below:

Child Component

interface OwnProps {
  style?: any;
}
interface ReduxStateProps {
  category: string;
}
interface DispatchProps {
  updateTimestamp: (timestamp: Date) => void;
}
type Props = ReduxStateProps & DispatchProps & OwnProps;

interface State {
  timestamp?: Date;
}

class ChildComponent extends React.Component<Props, State> {
  childMethod = () => {
    console.log("I am the child");
  };

  render(){
      <Text>Debug</Text>
  }
}

function mapStateToProps(state: any): ReduxStateProps {
  return {
    category: state.menu.category
  };
}

function mapDispatchToProps(dispatch: Dispatch<any>): DispatchProps {
  return {
    updateTimestamp: (timestamp: Date) =>
      dispatch(updateTimestampActionCreator(timestamp))
  };
}

export default connect<ReduxStateProps, DispatchProps, OwnProps>(
  mapStateToProps,
  mapDispatchToProps
)(ChildComponent);

Parent Component

class ParentComponent extends React.Component<{},{}> {
  private childComponent: any;

  render(){
    <View>
      <ChildComponent ref={ref => this.childComponent = ref as any}>
    </View>
  }
}

Here, the method "childMethod" is undefined when using the ref in the parent component. Without using connect, everything works fine.

vbvx
  • 609
  • 7
  • 22

1 Answers1

8

Doing this is generally labelled as bad practice. Another option that is generally a much better approach is to do the following.

class Parent extends React.Component {

   state = {
       functionToCallInChild = null;
   }

   render() {
       return (
           <Child setCallable={callable => this.setState({functionToCallInChild: callable})}/>
       );
   }
}

class Child extends React.Component {

    componentDidMount() {
       this.props.setCallable(this.childFunction);
    }

    childFunction = () => console.log("It worked!");

    render() {
       return (</div>);
    }
}

You can see, once the child renders, the parent now has access to call the child's function.

Francis Malloch
  • 1,074
  • 9
  • 20
  • 3
    can you detail a bit more why is it a bad practice? also, your approach solves my problem but doesn't answer the initial question so I don't think I can mark it as accepted answer – vbvx Jul 02 '18 at 09:37