我正在使用引导程序模态,并在元素上的单击事件上打开它,但是当我单击模态右上角的“ x”时无法关闭它。 问题是我确实通过道具成功地将状态从父项传递给子项,但是当我在子项内调用函数“ lgClose”时,它转到父项组件,但实际上并未将状态位置更改为“ false”。 我可以看到它进入函数内部,因为我输入了“ console.log('im in function')”,并且可以看到它。为什么在父组件中状态未更改为false?
import React, { Component } from 'react';
import { Link } from 'react-router-dom'
import { connect } from 'react-redux';
import { getAllUsers,getMessages } from './../actions';
import { bindActionCreators} from 'redux';
import { Button, Modal } from 'react-bootstrap';
import ContainerModal from './../components/popup_modal';
// parent component
class MainContainer extends Component {
constructor(props, context) {
super(props, context);
this.state = {
lgShow: false
};
}
componentWillMount(){
this.props.getAllUsers();
}
renderList = ({list}) => {
if(list){
return list.map((item)=>{
return(
<div key={item._id} className="item-list" onClick={() => this.setState({lgShow: true})}>
<div className="title">{item.firstName} {item.lastName}</div>
<div className="body">{item.age}</div>
<div>
<ContainerModal lgShow={this.state.lgShow} lgClose={this.lgClose}/>
</div>
</div>
)
})
}
}
lgClose = () => {
this.setState({lgShow:false});
console.log('im in the function');
}
render() {
console.log(this.state);
return (
<div className="App">
<div className="top">
<h3>Messages</h3>
<Link to="/form">Add</Link>
</div>
<div className="messages_container">
{this.renderList(this.props.users)}
</div>
</div>
);
}
}
function mapStateToProps(state) {
return {
messages:state.messages,
users:state.users
}
}
function mapDispatchToProps (dispatch) {
return bindActionCreators({getAllUsers,getMessages},dispatch);
}
export default connect(mapStateToProps,mapDispatchToProps)(MainContainer);
import React from 'react';
import { Button, Modal } from 'react-bootstrap';
// child component
const ContainerModal = (props) => {
return (
<div>
<Modal
size="lg"
show={props.lgShow}
onHide={ props.lgClose }
aria-labelledby="example-modal-sizes-title-lg"
>
<Modal.Header closeButton>
<Modal.Title id="example-modal-sizes-title-lg">
Large Modal
</Modal.Title>
</Modal.Header>
<Modal.Body>item</Modal.Body>
</Modal>
</div>
)
}
export default ContainerModal;
答案 0 :(得分:0)
似乎this
函数中的lgClose
没有指向MainContainer
。
如果是这种情况,一种解决方法是将lgClose
函数绑定到构造函数中的MainContainer:
constructor(props, context) {
super(props, context);
this.state = {
lgShow: false
};
this.lgClose = this.lgClose.bind(this); // Add this line
}
希望这会有所帮助:)
答案 1 :(得分:0)
在您的ContainerModal中尝试以下操作:
import React from 'react';
import { Button, Modal } from 'react-bootstrap';
// child component
const ContainerModal = (props) => {
return (
<div>
<Modal
{...props}
size="lg"
aria-labelledby="example-modal-sizes-title-lg"
>
<Modal.Header closeButton>
<Modal.Title id="example-modal-sizes-title-lg">
Large Modal
</Modal.Title>
</Modal.Header>
<Modal.Body>item</Modal.Body>
</Modal>
</div>
)
}
export default ContainerModal;
在renderList中,执行以下操作:
<ContainerModal show={this.state.lgShow} onHide={this.lgClose} />
答案 2 :(得分:0)
这是您的 lgShow 保持真实的原因。
此说明将稍长一些。所以,请忍受我。
这是您所做的。
您已将 ContainerModal 作为 div (className =“ item-list”)的子级添加到具有onClick的 renderList 方法中侦听器附加到自身。 当您单击列表项时,它可以正常工作并出现模态,但是当您单击模态上的关闭按钮时,事情就会变得混乱。
这是因为 div (className =“ item-list”)的onClick侦听器在 再次调用ContainerModal的点击监听器,将 lgShow 设置为 true 。这种行为称为事件冒泡,其中父级和子级都以自下而上的方式接收事件(即,子级接收第一个事件,随后是父级)。 要验证此行为,请在div的onClick侦听器中添加console.log。
这里是github问题的link,用于说明事件冒泡
解决方案
首要的建议是将ContainerModal从renderList方法取出到根div。这是因为现在正在为您的每个列表项创建一个ContainerModal,这是不必要的。例如,如果列表中有10个用户,则要创建10个ContainerModal(要验证这一点,可以增加用户数量,并且可以看到模式的阴影变得更暗。)
上述问题的解决方案是将ContainerModal置于其onClick的根级别,该根级别与renderList中 div (className =“ item-list”)的onClick不一致。您的问题将得到解决。
这是修改后的解决方案。
import React, { Component } from 'react';
import { Link } from 'react-router-dom'
import { connect } from 'react-redux';
import { getAllUsers,getMessages } from './../actions';
import { bindActionCreators} from 'redux';
import { Button, Modal } from 'react-bootstrap';
import ContainerModal from './../components/popup_modal';
// parent component
class MainContainer extends Component {
constructor(props, context) {
super(props, context);
this.state = {
lgShow: false
};
}
componentWillMount(){
this.props.getAllUsers();
}
renderList = ({list}) => {
if(list){
return list.map((item)=>{
return(
<div key={item._id} className="item-list" onClick={() => this.setState({lgShow: true})}>
<div className="title">{item.firstName} {item.lastName}</div>
<div className="body">{item.age}</div>
<div>
{/* <ContainerModal lgShow={this.state.lgShow} lgClose={this.lgClose}/> */}
</div>
</div>
)
})
}
}
lgClose = () => {
this.setState({lgShow:false});
console.log('im in the function');
}
render() {
console.log(this.state);
return (
<div className="App">
<div className="top">
<h3>Messages</h3>
<Link to="/form">Add</Link>
</div>
<div className="messages_container">
{this.renderList(this.props.users)}
</div>
<ContainerModal lgShow={this.state.lgShow} lgClose={this.lgClose}/>
</div>
);
}
}
function mapStateToProps(state) {
return {
messages:state.messages,
users:state.users
}
}
function mapDispatchToProps (dispatch) {
return bindActionCreators({getAllUsers,getMessages},dispatch);
}
export default connect(mapStateToProps,mapDispatchToProps)(MainContainer);
import React from 'react';
import { Button, Modal } from 'react-bootstrap';
// child component
const ContainerModal = (props) => {
return (
<div>
<Modal
size="lg"
show={props.lgShow}
onHide={ props.lgClose }
aria-labelledby="example-modal-sizes-title-lg"
>
<Modal.Header closeButton>
<Modal.Title id="example-modal-sizes-title-lg">
Large Modal
</Modal.Title>
</Modal.Header>
<Modal.Body>item</Modal.Body>
</Modal>
</div>
)
}
export default ContainerModal;
请注意容器模式的更改位置。其余代码都可以。
我还向代码沙箱上传了一个有效的解决方案。看看吧。
希望这会有所帮助。