【问题标题】:What is the right way to call child component functions in React using React.forwardRef()?使用 React.forwardRef() 在 React 中调用子组件函数的正确方法是什么?
【发布时间】:2020-08-21 03:32:28
【问题描述】:

我是新手,我正在尝试建立一个网站。我想从父组件触发子组件功能。即我有一个对话框组件和一个导航栏组件。 Navbar(child) 中的 Onclick 事件将 props 发送到 Display(parent) 并且该父组件必须触发 Dialogbox(child) 组件中的功能要启动对话框,并且此对话框必须根据用户输入将我的 true 或 false 返回给父组件。我已经设法做到了。真正的问题是我得到了

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

如果可以,有人可以告诉我一种更好的方法来以更简单的方式实现这些操作吗?如果是,请在我的githubhttps://github.com/kishorecmg/kishorecmg做同样的事情

谢谢。

【问题讨论】:

标签: javascript html reactjs web react-router


【解决方案1】:

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

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

DialogBox中,你可以使用componentDidUpdate来检查一个props是否发生了变化,然后触发一个动作:

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

【讨论】:

    猜你喜欢
    • 2020-04-16
    • 2021-03-23
    • 2022-01-14
    • 2018-12-20
    • 2020-09-18
    • 2021-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多