Как правильно вызывать функции дочерних компонентов в React с помощью React.forwardRef ()? - PullRequest
0 голосов
/ 06 мая 2020

Я новичок в реакции и пытаюсь создать веб-сайт. Я хотел вызвать функцию дочернего компонента из родительского компонента. т.е. у меня есть компонент Dialogbox и компонент Navbar. Событие Onclick на панели навигации ( дочерний ) отправляет реквизиты на дисплей ( родительский ), и этот родительский компонент должен запускать функцию в компоненте Dialogbox ( дочерний ) для запуска диалоговое окно, и это диалоговое окно должно возвращать мне истину или ложь в родительский компонент на основе ввода пользователя. И мне это удалось. Настоящая проблема в том, что я получаю предупреждение

index.js:1 Warning: findDOMNode is deprecated in StrictMode. findDOMNode was passed an instance of Transition which is inside StrictMode. Instead, add a ref directly to the element you want to reference. Learn more about using refs safely here
    in div (created by Transition)
    in Transition (created by ForwardRef(Fade))
    in ForwardRef(Fade) (created by ForwardRef(Backdrop))
    in ForwardRef(Backdrop) (created by WithStyles(ForwardRef(Backdrop)))
    in WithStyles(ForwardRef(Backdrop)) (created by ForwardRef(Modal))
    in div (created by ForwardRef(Modal))
    in ForwardRef(Portal) (created by ForwardRef(Modal))
    in ForwardRef(Modal) (created by ForwardRef(Dialog))
    in ForwardRef(Dialog) (created by WithStyles(ForwardRef(Dialog)))
    in WithStyles(ForwardRef(Dialog)) (at Dialogbox.js:48)
    in div (at Dialogbox.js:47)
    in AlertDialog (at Display.js:126)
    in div (at Display.js:120)
    in Router (created by BrowserRouter)
    in BrowserRouter (at Display.js:119)
    in Display (at App.js:10)
    in div (at App.js:9)
    in App (at src/index.js:12)
    in StrictMode (at src/index.js:11)

в консоли. Я не хочу игнорировать это предупреждение. Вот мой родительский компонент,

class Display extends React.Component
{

    constructor()
    {
        super()
        this.state = {language: english, changedLang: "null", isBackdrop: false}

        this.DialogRef = React.createRef();

    }

    languageSwitch(changedLanguage)
    {
        if(this.state.language.lang === "en" && changedLanguage === "jp")
        {
            this.setState({changedLang: changedLanguage})
            this.DialogRef.current.handleClickOpen()
            // this.refs.child.handleClickOpen()
        }
        else if(this.state.language.lang === "jp" && changedLanguage === "en")
        {
            this.setState({changedLang: changedLanguage})
            this.DialogRef.current.handleClickOpen()
            // this.refs.child.handleClickOpen()
        }
    }
    agreedOrNot(result)
    {
        if(this.state.language.lang === "en" && this.state.changedLang === "jp")
        {
            if(result)
            {
                this.setState({isBackdrop: true})
                setTimeout(()=> {this.setState({isBackdrop: false})}, 2500)

                setTimeout(()=> {this.setState({language: japanese})}, 2000)
            }
        }
        else if(this.state.language.lang === "jp" && this.state.changedLang === "en")
        {
            if(result)
            {
                this.setState({isBackdrop: true})
                setTimeout(()=> {this.setState({isBackdrop: false})}, 2500)

                setTimeout(()=> {this.setState({language: english})}, 2000)
            }
        }

        return result
    }

    render()
    {
        let backdrop

        if(this.state.isBackdrop)
        {
            backdrop = <LoadingScreen />
        }
        else
        {
            backdrop = <p/>
        }

        return(
            <div>
                <Navbar data={{language: this.state.language, 
                    languageSwitch: this.languageSwitch.bind(this)}} />

                {backdrop}
                    <Dialogbox ref={this.DialogRef} data={{language: this.state.language, 
                    agreedOrNot: this.agreedOrNot.bind(this)}} />

                </div>
        )
    }
}

export default Display

, а вот мой компонент Dialogbox.

class AlertDialog extends React.Component 
{
  constructor(props)
  {
    super(props)
    this.state = {open: false, loading: false}

    this.handleClickOpen = this.handleClickOpen.bind(this)
    this.handleCloseFalse = this.handleCloseFalse.bind(this)
    this.handleCloseTrue = this.handleCloseTrue.bind(this)
  }

  handleClickOpen()
  {
      this.setState({open: true})
  }

  handleCloseFalse = () =>
  {
      this.setState({open: false})
      this.props.data.agreedOrNot(false)
  }

  handleCloseTrue = () =>
  {
    this.setState({open: false})
    this.props.data.agreedOrNot(true)
  }

  render()
  {
    let currentLang = this.props.data.language.dialogbox

    return (
      <div>
        <Dialog open={this.state.open} onClose={this.handleClose}
          aria-labelledby="alert-dialog-title" aria-describedby="alert-dialog-description" >

          <DialogTitle id="alert-dialog-title">{currentLang.areYouSure}</DialogTitle>

          <DialogContent>
            <DialogContentText id="alert-dialog-description"> {currentLang.description} </DialogContentText>
          </DialogContent>

          <DialogActions>
            <Button onClick={this.handleCloseFalse} color="primary"> {currentLang.disagree} </Button>
            <Button onClick={this.handleCloseTrue} color="primary" autoFocus> {currentLang.agree} </Button>
          </DialogActions>

        </Dialog>
      </div>
    );
  }
}

export default AlertDialog

На самом деле я видел реализацию React.forwardRef () в функциональных компонентах, и реализации в классе мне несколько трудно понять должным образом. Может ли кто-нибудь помочь мне реализовать React.forwardRef () в классах?

Если можно, может кто-нибудь подскажет, как лучше реализовать эти действия более простым способом? Если да, сделайте то же самое в моем github https://github.com/kishorecmg/kishorecmg

Спасибо.

1 Ответ

1 голос
/ 06 мая 2020

Вы не можете использовать ref в компоненте React, вы можете использовать его только в элементе DOM (div, button, input ...). Вы не можете использовать ref для запуска функции Dialogbox, потому что ref не может быть прикреплен к Dialogbox, а только к одному из элементов, отображаемых Dialogbox. Следовательно, handleClickOpen не может быть вызван. forwardRef тоже не поможет.

Один из способов решить вашу проблему - передать реквизит дочернему компоненту, и этот реквизит может запускать действие

В DialogBox вы можете используйте componentDidUpdate, чтобы проверить, изменились ли свойства, а затем запустить действие:

componentDidUpdate(prevProps) {
    if (this.props.data.language !== prevProps.data.language) {
        this.setState({open: true})
    }
}
...