[英]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.innerRef
的ref
。 我的按钮组件(称为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.