React Childs 组件改变了他的 parents 状态
React Childs component changes his parents state
我正在做我的第一个更大的 React 项目,发现这个 bug/feature 我不知道如何解决。
问题
我想通过模态编辑用户。我打开它,但当我在该字段中更改某些内容时,parent 的组件状态也会发生变化。 Child 组件正在改变 parent 状态而没有传递函数。
我的方法
我尝试更改变量名称,因为我认为不可能更改 parent 组件状态。然后我在状态改变时开始记录。在 handle change 中第一次调用 this.props.log()
时,状态发生改变。
Parent 分量
class UserAdminPage extends Component {
constructor(props) {
super(props);
this.state = {
performingAction: false,
editorIsOpened: false,
selectedUser: {}
}
}
componentDidMount() {
userService.getAll().then(res => {
const users = res;
this.setState({users});
})
}
openEditModal = id => {
const user = this.state.users.filter(u => u.id === id)[0];
this.setState({selectedUser: user}, () => {
this.setState({editorIsOpened: true})
console.log("Selected user", this.state.selectedUser);
});
}
closeModal = () => {
console.log("Close values",this.state.users, this.state.selectedUser);
/*if (!save) {
console.log("Throwing away");
this.setState({editorIsOpened: false});
return;
}
console.log("Saving");
this.setState({editorIsOpened: false});*/
}
log = ()=>{
console.log("Logged user",this.state.users);
}
render() {
const {users} = this.state;
return (
users ? (
<React.Fragment>
<MDBRow className={"my-5"}/>
<UserTable users={users} openEditModal={this.openEditModal}
performingAction={this.state.performingAction}/>
{this.state.editorIsOpened && <UserEditorModal user={this.state.selectedUser}
closeModal={this.closeModal} log={this.log}/>}
</React.Fragment>
) : (
<LaunchScreen/>
)
)
}
}
和child
class UserEditorModal extends Component {
constructor(props) {
super(props);
this.state = {
selectedUser: props.user
}
console.log("Modal user",this.state.selectedUser)
}
handleChange = (e) => {
this.props.log();//here is different output
const [field, value] = [e.target.name, e.target.value]
const parsedValue = parseInt(value)
const user = this.state.selectedUser;
user.hasOwnProperty(field) ? user[field] = isNaN(parsedValue)?value:parsedValue : console.error(`${field} not found on ${user}`);
this.setState({selectedUser:user});
this.props.log();
}
render() {
const user = this.state.selectedUser;
const modal = true;
return (
<React.Fragment>
<MDBModal isOpen={modal} toggle={() => this.props.closeModal(null, false)} fullHeight
position="right">
<MDBModalHeader toggle={() => this.props.closeModal()}>User editor</MDBModalHeader>
<MDBModalBody>
<MDBRow>
<MDBCol size="3">
<MDBInput type='number' name="karma" label="Karma" value={user.karma}
onChange={e => this.handleChange(e)}/>
</MDBCol>
<MDBCol size="3">
<MDBInput type='number' name="money" label="Money" value={user.money}
onChange={e => this.handleChange(e)}/>
</MDBCol>
<MDBCol>
<MDBInput type="text" value={user.email} disabled/>
</MDBCol>
</MDBRow>
<MDBRow>
<MDBCol size="md">
<MDBInput type='text' name="firstName" label="First name" value={user.firstName}
onChange={e => this.handleChange(e)}/>
</MDBCol>
<MDBCol size="md">
<MDBInput type='text' name="lastName" label="Last name" value={user.lastName}
onChange={e => this.handleChange(e)}/>
</MDBCol>
</MDBRow>
</MDBModalBody>
<MDBModalFooter>
<MDBBtn color="secondary"
onClick={() => this.props.closeModal()}>Close</MDBBtn>
<MDBBtn color="primary" onClick={() => this.props.closeModal()}>Save
changes</MDBBtn>
</MDBModalFooter>
</MDBModal>
</React.Fragment>
);
}
}```
I must missing something but couldnt find it. Hope you can find it and help me once again
猜想是因为您正在使用引用来更改状态。
因此,最终当您更改 child 组件的状态时,parent 的状态也会更改,但 parent 不会 re-render.
constructor(props) {
super(props);
this.state = {
selectedUser: {...props.user}
}
console.log("Modal user",this.state.selectedUser)
}
尝试在您的 child 中使用它。
我正在做我的第一个更大的 React 项目,发现这个 bug/feature 我不知道如何解决。
问题
我想通过模态编辑用户。我打开它,但当我在该字段中更改某些内容时,parent 的组件状态也会发生变化。 Child 组件正在改变 parent 状态而没有传递函数。
我的方法
我尝试更改变量名称,因为我认为不可能更改 parent 组件状态。然后我在状态改变时开始记录。在 handle change 中第一次调用 this.props.log()
时,状态发生改变。
Parent 分量
class UserAdminPage extends Component {
constructor(props) {
super(props);
this.state = {
performingAction: false,
editorIsOpened: false,
selectedUser: {}
}
}
componentDidMount() {
userService.getAll().then(res => {
const users = res;
this.setState({users});
})
}
openEditModal = id => {
const user = this.state.users.filter(u => u.id === id)[0];
this.setState({selectedUser: user}, () => {
this.setState({editorIsOpened: true})
console.log("Selected user", this.state.selectedUser);
});
}
closeModal = () => {
console.log("Close values",this.state.users, this.state.selectedUser);
/*if (!save) {
console.log("Throwing away");
this.setState({editorIsOpened: false});
return;
}
console.log("Saving");
this.setState({editorIsOpened: false});*/
}
log = ()=>{
console.log("Logged user",this.state.users);
}
render() {
const {users} = this.state;
return (
users ? (
<React.Fragment>
<MDBRow className={"my-5"}/>
<UserTable users={users} openEditModal={this.openEditModal}
performingAction={this.state.performingAction}/>
{this.state.editorIsOpened && <UserEditorModal user={this.state.selectedUser}
closeModal={this.closeModal} log={this.log}/>}
</React.Fragment>
) : (
<LaunchScreen/>
)
)
}
}
和child
class UserEditorModal extends Component {
constructor(props) {
super(props);
this.state = {
selectedUser: props.user
}
console.log("Modal user",this.state.selectedUser)
}
handleChange = (e) => {
this.props.log();//here is different output
const [field, value] = [e.target.name, e.target.value]
const parsedValue = parseInt(value)
const user = this.state.selectedUser;
user.hasOwnProperty(field) ? user[field] = isNaN(parsedValue)?value:parsedValue : console.error(`${field} not found on ${user}`);
this.setState({selectedUser:user});
this.props.log();
}
render() {
const user = this.state.selectedUser;
const modal = true;
return (
<React.Fragment>
<MDBModal isOpen={modal} toggle={() => this.props.closeModal(null, false)} fullHeight
position="right">
<MDBModalHeader toggle={() => this.props.closeModal()}>User editor</MDBModalHeader>
<MDBModalBody>
<MDBRow>
<MDBCol size="3">
<MDBInput type='number' name="karma" label="Karma" value={user.karma}
onChange={e => this.handleChange(e)}/>
</MDBCol>
<MDBCol size="3">
<MDBInput type='number' name="money" label="Money" value={user.money}
onChange={e => this.handleChange(e)}/>
</MDBCol>
<MDBCol>
<MDBInput type="text" value={user.email} disabled/>
</MDBCol>
</MDBRow>
<MDBRow>
<MDBCol size="md">
<MDBInput type='text' name="firstName" label="First name" value={user.firstName}
onChange={e => this.handleChange(e)}/>
</MDBCol>
<MDBCol size="md">
<MDBInput type='text' name="lastName" label="Last name" value={user.lastName}
onChange={e => this.handleChange(e)}/>
</MDBCol>
</MDBRow>
</MDBModalBody>
<MDBModalFooter>
<MDBBtn color="secondary"
onClick={() => this.props.closeModal()}>Close</MDBBtn>
<MDBBtn color="primary" onClick={() => this.props.closeModal()}>Save
changes</MDBBtn>
</MDBModalFooter>
</MDBModal>
</React.Fragment>
);
}
}```
I must missing something but couldnt find it. Hope you can find it and help me once again
猜想是因为您正在使用引用来更改状态。 因此,最终当您更改 child 组件的状态时,parent 的状态也会更改,但 parent 不会 re-render.
constructor(props) {
super(props);
this.state = {
selectedUser: {...props.user}
}
console.log("Modal user",this.state.selectedUser)
}
尝试在您的 child 中使用它。