Search code examples
javascriptreactjsref

React: problem calling child function in parent component


I made a games page in react. When you win one, it displays a form dialog (with material-UI: https://material-ui.com/components/dialogs/#form-dialogs). Component's visibility depends on the open attribute, which is changed with "handleClickOpen" when you push the button. I wanted to reuse code so I made a component that contains the dialog. Here is my code so far (child class):

class Pop_dialog extends Component {
constructor(props) {
    super(props)

    this.state = {
        open: false
    }
}

handleOpen() {
    console.log('A')
    this.setState({ open: true })
}
handleClose() {
    console.log('B')
    this.setState({ open: false })
}

render() {
    return (
        <Dialog open={this.state.open} onClose={this.handleClose} aria-labelledby="form-dialog-title">
            <DialogTitle id="form-dialog-title">Subscribe</DialogTitle>
            <DialogContent>
                <DialogContentText>
                    To subscribe to this website, please enter your email address here. We will send updates
                    occasionally.
                </DialogContentText>
                <TextField
                    autoFocus
                    margin="dense"
                    id="name"
                    label="Email Address"
                    type="email"
                    fullWidth
                />
            </DialogContent>
            <DialogActions>
                <Button onClick={this.handleClose} color="primary">
                    Cancel
                </Button>
                <Button onClick={this.handleClose} color="primary">
                    Subscribe
                </Button>
            </DialogActions>
        </Dialog>
    )
}

I call "handleOpen" within a function in the parent class:

triggerDialog() { this.dialogRef.current.handleOpen(); }

render ()
{
  ...
  <Pop_dialog ref={this.dialogRef}/>
}

The triggerDialog function is called when I win/lost the game and it opens the form dialog fine. The problem comes when I try to close it (with the Cancel or Subscribe buttons). The page throws the next error:

enter image description here

I couldn´t find why it fails here but not when it use "handleOpen". By the way, this is the 4th solution that i use. I also tried using a function component with the useContext hood (It didn't work at all), passing 'open' like a prop to the child (I also could open the dialog but not close it) and turn 'open' in a session var, defined in the parent component and called in the child (I couldn't open the dialog).

I don't know if some of this ideas would work or if I need a completely new one. I am open to any kind of idea, as long as it keeps Pop_dialog reusable.


Solution

  • It doesn't seem as though you've bound this to the handlers in Pop_dialog. The result is that this is undefined in the callback handlers.

    Bind in the constructor:

    class Pop_dialog extends Component {
      constructor(props) {
        super(props)
    
        this.state = {
            open: false
        }
        this.handleOpen = this.handleOpen.bind(this);
        this.handleClose = this.handleClose.bind(this);
      }
    
      handleOpen() {
        console.log('A')
        this.setState({ open: true })
      }
      handleClose() {
        console.log('B')
        this.setState({ open: false })
      }
      ...
    

    Or convert the handlers to arrow functions so this of the class is bound automatically.

    class Pop_dialog extends Component {
      constructor(props) {
        super(props)
    
        this.state = {
            open: false
        }
      }
    
      handleOpen = () => {
        console.log('A')
        this.setState({ open: true })
      }
      handleClose = () => {
        console.log('B')
        this.setState({ open: false })
      }
      ...