我试图通过父组件中的按钮单击事件来调用子组件中的函数。
父组件:
class Parent extends Component{
constructor(props){
super(props);
this.state = {
//..
}
}
handleSaveDialog = (handleSaveClick) => {
this.handleSaveClick = handleSaveClick;
}
render(){
return(
<div>
<Button onClick={this.openDialog}>Open Dialog</Button>
<Dialog>
<DialogTitle id="form-dialog-title">Child Dialog</DialogTitle>
<DialogContent>
<Child handleSaveData={this.handleSaveDialog}/>
</DialogContent>
<DialogActions>
<Button onClick={this.handleSaveClick} color="primary">
Save
</Button>
</DialogActions>
</Dialog>
</div>
);
}
}
在上面的代码中,单击按钮后,父组件将呈现子组件模态对话框(基于Material-UI)。单击“保存”按钮,是“父项”中Dialog
组件的一部分,应在Child
组件中调用保存功能。如您所见,我已经通过名为handleSaveDialog
的{{1}}组件道具传递了一个回调函数Child
。一旦子组件安装并将回调传递给父组件,单击保存按钮将在子组件上调用handleSaveData
。
子组件:
handleSaveClick
在上面的代码中,我正在使用class Child extends Component{
constructor(props){
super(props);
this.state = {
//..
}
}
componentDidMount(){
console.log('mount');
this.props.handleSaveData( () => this.handleSaveClick());
}
handleSaveClick = () => {
console.log('save clicked');
}
render(){
return(
<div>
//..
</div>
);
}
}
组件props传递的回调函数,并将其绑定到Parent
组件的保存功能Child
。
问题:
当我第一次单击“父项”中的“打开对话框”按钮时,handleSaveClick
会挂载“子项”组件。但是,单击Dialog
按钮无效(没有错误)。关闭对话框之后,当我重新打开对话框并单击“保存”时,将触发“子”对话框中的Save
,并在浏览器控制台中记录一条消息。知道为什么第二次而不是第一次有效吗?
请记住,只有当我单击父组件上的“打开对话框”时,才会装入/加载子组件。
参考文献:
https://material-ui.com/components/dialogs/#form-dialogs
https://github.com/kriasoft/react-starter-kit/issues/909#issuecomment-390556015
答案 0 :(得分:2)
好吧,我不知道为什么会有这种情况,但是我想到的第一件事就是可以在Parent组件中编写handleSaveClick
方法。并且如果您需要在子组件中可能发生的任何操作上使用该函数,则可以将该函数作为父组件的prop传递。这样您的两种情况都可以处理
如果您仍然认为必须在子组件中定义方法,则可以使用refs
答案 1 :(得分:1)
它将不起作用,因为如果您在this.handleSaveClick
功能中管理日志render
,则它将是undefined
,因为没有重新渲染。因此,有两种方法可以实现:
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
open: false
};
}
openDialog = () => {
this.setState(preState => ({
open: !preState.open
}));
};
handleSaveDialog = handleSaveRef => {
this.setState({
handleSaveClick: handleSaveRef
});
};
render() {
console.log("Render", this.handleSaveClick);
return (
<div>
<Button onClick={this.openDialog}>Open Dialog</Button>
<Dialog open={this.state.open}>
<DialogTitle id="form-dialog-title">Child Dialog</DialogTitle>
<DialogContent>
<Child handleSaveData={this.handleSaveDialog} />
</DialogContent>
<DialogActions>
<Button onClick={this.state.handleSaveClick} color="primary">
Save
</Button>
</DialogActions>
</Dialog>
</div>
);
}
class Child extends Component {
componentDidMount() {
console.log("mount");
this.props.handleSaveData(this.handleSaveClick);
}
handleSaveClick = () => {
console.log("save clicked");
};
render() {
return <div>//..</div>;
}
}
const childRef = React.createRef();
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
open: false
};
}
openDialog = () => {
this.setState(preState => ({
open: !preState.open
}));
};
handleSaveClick = () => {
if (childRef.current) {
childRef.current.handleSaveClick();
}
};
render() {
return (
<div>
<Button onClick={this.openDialog}>Open Dialog</Button>
<Dialog open={this.state.open}>
<DialogTitle id="form-dialog-title">Child Dialog</DialogTitle>
<DialogContent>
<Child ref={childRef} />
</DialogContent>
<DialogActions>
<Button onClick={this.handleSaveClick} color="primary">
Save
</Button>
</DialogActions>
</Dialog>
</div>
);
}
}
class Child extends Component {
handleSaveClick = () => {
console.log("save clicked");
};
render() {
return <div>//..</div>;
}
}
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
open: false
};
}
openDialog = () => {
this.setState(preState => ({
open: !preState.open
}));
};
handleSaveDialog = handleSaveRef => {
this.handleSaveClick = handleSaveRef;
};
render() {
return (
<div>
<Button onClick={this.openDialog}>Open Dialog</Button>
<Dialog open={this.state.open}>
<DialogTitle id="form-dialog-title">Child Dialog</DialogTitle>
<DialogContent>
<Child handleSaveData={this.handleSaveDialog} />
</DialogContent>
<DialogActions>
<Button onClick={() => this.handleSaveClick()} color="primary">
Save
</Button>
</DialogActions>
</Dialog>
</div>
);
}
}
class Child extends Component {
componentDidMount() {
console.log("mount");
this.props.handleSaveData(this.handleSaveClick);
}
handleSaveClick = () => {
console.log("save clicked");
};
render() {
return <div>//..</div>;
}
}
您将需要在onClick
中使用箭头函数,因为每次单击鼠标键都会创建一个新函数,从而获得handleClick
的新实例。而且,如果您通过this.handleClick
,则将无法使用,因为它是undefined
。您可以通过在this.handleClick
函数中记录render
的值来进行检查。
注意:使用2
选项更可靠。
希望这会有所帮助!