React父组件控制子组件状态:关闭弹窗时重置setStyle
React弹窗关闭时重置子组件状态的解决方案
问题描述
点击子组件中的「SET STYLE」按钮后,setStyle状态设为true,弹窗会应用新样式,但关闭弹窗后setStyle仍保持true,需要在弹窗关闭时将其重置为false。曾尝试将setStyle放在父组件,但不知道如何在子组件中修改父组件状态。
原代码
class ParentComponent extends Component { state = { isDialogOpen: false } handleClose = () => { this.setState({ isDialogOpen: false }) } handleOpen = () => { this.setState({ isDialogOpen: true }) } render() { return ( <div> <Button onClick={() => this.handleOpen}>Open Dialog</Button> <ChildComponent isOpen={isDialogOpen} onClose={this.handleClose}> </div> ) } } class ChildComponent extends Component { constructor(props) { super(props) this.state = { setStyle: false } } componentDidUpdate(prevProps, prevState) { if(!isOpen && prevProps.isOpen && setStyle !== prevState.setStyle) { // make some API call here to fetch and display data in dialog box // action from react-redux someAPIfunction() } handleSetStyle() { this.setState({ setStyle: true }) } const {setStyle } = this.state; const showTextStyle = setStyle ? 'some-css' : null render() { return <DialogComponentLibrary isOpen={isOpen} onClose={onClose}> <p className={showTextStyle}>{someDataFromAPI}</p> <Button onClick={this.handleSetStyle}>SET STYLE</Button> </Dialog> } }
解决方案
方案一:子组件内部监听弹窗状态重置
利用类组件的componentDidUpdate生命周期,监听isOpen属性的变化,当弹窗从打开变为关闭时,直接重置子组件内部的setStyle状态。
修改后的子组件代码:
class ChildComponent extends Component { constructor(props) { super(props) this.state = { setStyle: false } } componentDidUpdate(prevProps) { // 弹窗从打开切到关闭时,重置setStyle if (!this.props.isOpen && prevProps.isOpen) { this.setState({ setStyle: false }); } // 保留原有的API调用逻辑(修正变量引用问题) if(!this.props.isOpen && prevProps.isOpen && this.state.setStyle !== prevState.setStyle) { someAPIfunction() } } // 改用箭头函数避免this绑定问题 handleSetStyle = () => { this.setState({ setStyle: true }) } render() { const { setStyle } = this.state; const showTextStyle = setStyle ? 'some-css' : null; const { isOpen, onClose } = this.props; return ( <DialogComponentLibrary isOpen={isOpen} onClose={onClose}> <p className={showTextStyle}>{someDataFromAPI}</p> <Button onClick={this.handleSetStyle}>SET STYLE</Button> </DialogComponentLibrary> ) } }
方案二:状态提升到父组件(解决你之前的痛点)
把setStyle状态移到父组件,同时传递一个修改该状态的方法给子组件,父组件在关闭弹窗时直接重置setStyle,子组件通过调用父组件方法来修改状态。
修改后的父组件:
class ParentComponent extends Component { state = { isDialogOpen: false, setStyle: false // 把状态移到父组件 } handleClose = () => { // 关闭弹窗时同时重置setStyle this.setState({ isDialogOpen: false, setStyle: false }) } handleOpen = () => { this.setState({ isDialogOpen: true }) } // 提供给子组件修改setStyle的方法 handleSetStyle = () => { this.setState({ setStyle: true }) } render() { const { isDialogOpen, setStyle } = this.state; return ( <div> {/* 修正原onClick的错误,直接传方法即可 */} <Button onClick={this.handleOpen}>Open Dialog</Button> <ChildComponent isOpen={isDialogOpen} onClose={this.handleClose} setStyle={setStyle} onSetStyle={this.handleSetStyle} /> </div> ) } }
修改后的子组件:
class ChildComponent extends Component { constructor(props) { super(props) // 移除子组件内部的setStyle状态 } componentDidUpdate(prevProps) { // 保留原API逻辑(改用props中的setStyle) if(!this.props.isOpen && prevProps.isOpen && this.props.setStyle !== prevProps.setStyle) { someAPIfunction() } } render() { const { setStyle, isOpen, onClose, onSetStyle } = this.props; const showTextStyle = setStyle ? 'some-css' : null; return ( <DialogComponentLibrary isOpen={isOpen} onClose={onClose}> <p className={showTextStyle}>{someDataFromAPI}</p> <Button onClick={onSetStyle}>SET STYLE</Button> </DialogComponentLibrary> ) } }
内容的提问来源于stack exchange,提问作者Kalamazoo
相关产品推荐
相关产品推荐

