繁体   English   中英

使用 React.forwardRef() 在 React 中调用子组件函数的正确方法是什么?

[英]What is the right way to call child component functions in React using React.forwardRef()?

我是新手,我正在尝试建立一个网站。 我想从父组件触发子组件 function 。 即我有一个对话框组件和一个导航栏组件。 导航栏()中的 Onclick 事件将道具发送到显示(),并且该父组件必须触发对话框()组件中的 function 以启动对话框,并且此对话框必须根据用户输入。 我已经设法做到了。 真正的问题是我得到

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

这是我的对话框组件。

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() 的实现,而 class 中的实现对我来说有点难以正确理解。 有人可以帮我在类中实现 React.forwardRef() 吗?

如果可以,有人可以告诉我以更简单的方式实现这些操作的更好方法吗? 如果是,请在我的 github https://github.com/kishorecmg/kishorecmg中执行相同操作

谢谢你。

您不能在 React 组件上使用ref ,只能在 DOM 元素(div、按钮、输入...)上使用它。 您不能使用ref来触发Dialogbox function 因为ref不能附加到Dialogbox而只能附加到Dialogbox呈现的元素之一。 因此无法调用handleClickOpen forwardRef也无济于事。

解决问题的一种方法是将道具传递给子组件,道具可以触发动作

DialogBox中,您可以使用componentDidUpdate检查道具是否已更改,然后触发操作:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM