我有一个React应用,其界面使用Material UI。我创建了一个自定义按钮组件,该组件可为默认的Material UI按钮设置样式,并且还使用redux。
我的按钮组件的ActivityLog.XML
功能如下:
render()
我想要的是能够在页面上包含此按钮,并使UI通过单击以外的其他方式触发其click事件。例如,在登录表单上,我希望当前专注于密码文本框的用户能够通过单击Return / Enter键来触发按钮单击。
我确定我需要在React中使用转发引用的概念,但是我对React还是很陌生,无法使其正常工作。您可以在我的按钮上看到我已将 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>
);
设置为ref
。我的按钮组件(称为this.props.innerRef
)是这样导出的:
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
初始化了构造函数中的ref
最后this.submitButton = React.createRef();
看起来像这样:
triggerClick
当我在文本框中按下Enter键时,我可以检查分配给 triggerClick() {
console.log('CLICK', this.submitButton.current);
this.submitButton.current.click();
}
的值,并可以看到它是包装按钮的Redux this.submitButton.current
对象。但是,我也收到错误connect
,因此很明显,引用并没有一直转发到按钮本身。
恐怕我有点迷失了,所以呼吁您的帮助!
答案 0 :(得分:2)
仅需确保,您想要的是:当用户在文本字段上键入时按Enter
时,该按钮将显示正在加载的图像,对吗?
我认为您不必将ref传递给按钮组件,只需将状态isLoadingShown
传递给WaitingButton
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>
...
}
不要忘记在isLoadingShown
中将componentWillUnmount
再次设置为false
答案 1 :(得分:1)
我只是想重现您的情况。我为此创建了一个codeandbox。我想我找到了问题。看来React.forwardRef仅适用于道具名称forwardedRef,因此请尝试在代码中将innerRef属性重命名为forwardedRef。
const withInnerRef = React.forwardRef((props, ref) => <WaitingButton
forwardedRef={ref} {...props}
/>);
以及您的render()函数中
<Button
ref={this.props.forwardedRef}
disabled={loading || disabled}
onClick={this.handleClick}
...
您可以尝试使用我的简化代码和框https://codesandbox.io/s/intelligent-cori-rb5ce