繁体   English   中英

在 React 中,如何从不同组件的事件处理程序触发自定义按钮的单击事件?

[英]In React how can I trigger a custom button's click event from a different compoennt's event handler?

我有一个使用Material UI作为界面的 React 应用程序。 我创建了一个自定义按钮组件,其中 styles 是默认的 Material UI 按钮,并且还使用了 redux。

我的按钮组件的render() function 如下所示:

        return (
            <div className={classes.buttonWrapper}>
                <Button 
                    ref={this.props.innerRef}
                    disabled={loading || disabled}
                    onClick={this.handleClick}
                    {...other}>
                    <React.Fragment>
                        {children}
                        {this.buildLoader(loading, classes)}
                    </React.Fragment>
                </Button>
            </div>
        );

我想要的是能够在页面上包含这个按钮,并让 UI 通过点击它以外的其他方式触发它的点击事件。 例如,在登录表单上,我希望当前关注密码文本框的用户能够通过按 Return/Enter 键触发按钮单击。

我确定我需要在 React 中使用转发 refs 的概念,但我对 React 还很陌生,无法让它工作。 你可以在我的按钮上看到我已经定义了一个设置为this.props.innerRefref 我的按钮组件(称为WaitingButton )是这样导出的:

const withInnerRef = React.forwardRef((props, ref) => <WaitingButton 
  innerRef={ref} {...props}
/>);

var component = withStyles(styles)(withInnerRef);

export default connect(mapStateToProps, mapDispatchToProps)(component);

然后我将此按钮添加到这样的表单中:

    <Paper>
        <TextField 
            style={{marginBottom: '8px'}}
            label="A textbox!"
            fullWidth 
            onKeyPress={(e) => { if (e.key === "Enter") this.triggerClick(); }} />
        <WaitingButton 
            ref={this.submitButton}
            variant="contained"
            color="primary"
            onClick={(e) => {
                console.log('Button clicked :)', e.target);
            }}>
            Press enter in textbox!
        </WaitingButton>
    </Paper>

请参阅我已分配按钮的ref并在此页面的构造函数中我已使用this.submitButton = React.createRef();初始化构造函数中的 ref

最后triggerClick看起来像这样:

    triggerClick() {
        console.log('CLICK', this.submitButton.current);
        this.submitButton.current.click();
    }

当我在文本框中按回车键时,我可以检查分配给this.submitButton.current的值,可以看到它是 Redux connect object ,我用它包裹了我的按钮。 但是,我也收到错误this.submitButton.current.click is not a function所以很明显 ref 没有一直转发到按钮本身。

恐怕我有点迷失了,所以请求你的帮助!

只是想确保,您想要的是:当用户在文本字段上键入时按Enter ,按钮将显示加载视觉效果,对吗? 我认为您不必将 ref 传递给按钮组件,您只需将 state isLoadingShown传递到您的WaitingButton

等待按钮.js

 return (
        <div className={classes.buttonWrapper}>
            <Button 
                ref={this.props.innerRef}
                disabled={loading || disabled}
                onClick={this.handleClick}
                {...other}>
                <React.Fragment>
                    {children}
                    {this.props.isLoadingShown && this.buildLoader(loading, classes)}
                </React.Fragment>
            </Button>
        </div>
    );

然后在表单组件中

state = {
   isLoadingShown: false,
}

triggerClick() {
    this.setState({ isLoadingShown: true })
}

render(){
   ...
   <Paper>
       <TextField 
           style={{marginBottom: '8px'}}
           label="A textbox!"
           fullWidth 
           onKeyPress={(e) => { if (e.key === "Enter") this.triggerClick(); }} />
       <WaitingButton
           variant="contained"
           color="primary"
           isLoadingShown={this.state.isLoadingShown}
           onClick={(e) => {
               console.log('Button clicked :)', e.target);
           }}>
           Press enter in textbox!
       </WaitingButton>
   </Paper>
   ...
}

不要忘记在componentWillUnmount中再次将isLoadingShown设置为 false

我只是试图重现你的情况。 我为它创建了一个代码框。 我想我找到了问题所在。 似乎 React.forwardRef 仅适用于道具名称 forwardedRef 因此尝试在代码中将 innerRef 属性重命名为 forwardedRef 。

const withInnerRef = React.forwardRef((props, ref) => <WaitingButton 
  forwardedRef={ref} {...props}
/>);

以及你的 render() function

<Button 
    ref={this.props.forwardedRef}
    disabled={loading || disabled}
    onClick={this.handleClick}
    ...

你可以用我的简化代码盒https://codesandbox.io/s/intelligent-cori-rb5ce 试试

暂无
暂无

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

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