我正在构建一个React组件,用户可以在其中选择选项,并且一旦用户在选择后单击“保存”,就将选项保存为状态。但是,在第一次单击保存后(在模态内部),不会保存它。关闭模态并再次打开后,最后选择的选项将被保存。
Sample.js
import React, { Component } from "react";
import Modal from "./Modal";
class Sample extends Component {
constructor(props) {
super(props);
this.state = {
users: [],
usersUn: [
{ id: 1, name: "kepa" },
{ id: 2, name: "rudiger" },
{ id: 3, name: "alonso" },
{ id: 4, name: "Christensen" },
{ id: 7, name: "Kante" },
{ id: 8, name: "Barkley" },
{ id: 9, name: "Tammy" },
{ id: 10, name: "willian" },
{ id: 11, name: "pedro" },
{ id: 12, name: "Loftus-Cheek" },
{ id: 13, name: "Caballero" },
{ id: 15, name: "Zouma" },
{ id: 18, name: "Giroud" },
{ id: 19, name: "Mount" },
{ id: 20, name: "Hudson-Odoi" },
{ id: 22, name: "Pulisic" },
{ id: 23, name: "Batshuayi" },
{ id: 24, name: "James" },
{ id: 28, name: "azpilicueta" },
{ id: 29, name: "tomori" },
{ id: 33, name: "Emerson" }
],
usersSel: [{ id: 17, name: "kovacic" }, { id: 5, name: "jorginho" }],
isLoading: false,
err: null
};
}
save = (itemsLeft, itemsRight) => {
this.setState({
usersUn: itemsLeft,
usersSel: itemsRight
});
};
render() {
return (
<Modal
usersUn={this.state.usersUn}
usersSel={this.state.usersSel}
loading={this.state.isLoading}
err={this.state.err}
title="Gimme a title"
leftTitle="Squad"
rightTitle="PL11"
save={this.save}
/>
);
}
}
export default Sample;
Modal.js
import React, { Component } from "react";
import Popup from "reactjs-popup";
class Modal extends Component {
constructor(props) {
super(props);
this.state = {
open: false,
itemsLeft: this.props.usersUn,
itemsRight: this.props.usersSel,
selectedLeft: [],
selectedRight: [],
filterLeft: "",
filterRight: ""
};
}
openModal = () => {
this.setState({ open: true });
};
closeModal = () => {
this.setState({
open: false,
itemsLeft: this.props.usersUn,
itemsRight: this.props.usersSel
});
};
handleChange = e => {
this.setState({ [e.target.name]: e.target.value });
};
selectLeft = id => {
const selectedVal = this.state.itemsLeft.filter(user => user.id === id);
// console.log(selectedVal);
this.setState(prevState => {
return {
selectedLeft: [...prevState.selectedLeft, ...selectedVal]
};
});
};
selectRight = id => {
const selectedVal = this.state.itemsRight.filter(user => user.id === id);
// console.log(selectedVal);
this.setState(prevState => {
return {
selectedRight: [...prevState.selectedRight, ...selectedVal]
};
});
};
moveAllRight = () => {
this.setState(prevState => {
return {
itemsLeft: [],
itemsRight: [...prevState.itemsRight, ...prevState.itemsLeft]
};
});
};
moveRight = () => {
const updatedItemsLeft = this.state.itemsLeft.filter(item => {
for (var i = 0; i < this.state.selectedLeft.length; i++) {
if (this.state.selectedLeft[i].id === item.id) return false;
}
return true;
});
const updatedItemsRight = [
...this.state.itemsRight,
...this.state.selectedLeft
];
this.setState({
itemsLeft: updatedItemsLeft,
itemsRight: updatedItemsRight,
selectedLeft: []
});
};
moveLeft = () => {
const updatedItemsRight = this.state.itemsRight.filter(item => {
for (var i = 0; i < this.state.selectedRight.length; i++) {
if (this.state.selectedRight[i].id === item.id) return false;
}
return true;
});
const itemsLeft = [...this.state.itemsLeft, ...this.state.selectedRight];
this.setState({
itemsLeft: itemsLeft,
itemsRight: updatedItemsRight,
selectedRight: []
});
};
moveAllLeft = () => {
this.setState(prevState => {
return {
itemsRight: [],
itemsLeft: [...prevState.itemsLeft, ...prevState.itemsRight]
};
});
};
saveList = () => {
this.props.save(this.state.itemsLeft, this.state.itemsRight);
this.closeModal();
};
filterItems = (items, filterTxt) => {
return items.filter(item =>
item.name.toLowerCase().includes(filterTxt.toLowerCase())
);
};
render() {
const { loading, err, title, leftTitle, rightTitle } = this.props;
const { itemsLeft, itemsRight, filterLeft, filterRight } = this.state;
const filteredDataL = this.filterItems(itemsLeft, filterLeft);
const filteredDataR = this.filterItems(itemsRight, filterRight);
if (loading) {
return <div>Loading...</div>;
}
if (err) {
return <div>{err}</div>;
}
return (
<>
<button className="button" onClick={this.openModal}>
Open Modal
</button>
<Popup open={this.state.open} modal closeOnDocumentClick>
<div className="modal__content">
<div className="modal__header">
<h4>{title}</h4>
<button onClick={this.closeModal}>×</button>
</div>
<div className="modal__body">
<div>
<h4>
{leftTitle}
{`(${itemsLeft.length})`}
</h4>
<div>
<input
type="search"
name="filterLeft"
placeholder="search"
value={filterLeft}
onChange={this.handleChange}
/>
</div>
<div className="results">
{filteredDataL.map(user => {
return (
<div
className="list__item"
key={user.name}
onClick={() => this.selectLeft(user.id)}
>
{user.name}
{`(${user.id})`}
</div>
);
})}
</div>
</div>
<div className="controls">
<button onClick={this.moveAllRight}>>></button>
<button onClick={this.moveRight}>></button>
<button onClick={this.moveLeft}><</button>
<button onClick={this.moveAllLeft}><<</button>
</div>
<div>
<h4>
{rightTitle}
{`(${itemsRight.length})`}
</h4>
<div>
<input
type="search"
placeholder="search"
name="filterRight"
value={filterRight}
onChange={this.handleChange}
/>
</div>
<div className="results">
{filteredDataR.map(user => {
return (
<div
className="list__item"
key={user.name}
onClick={() => this.selectRight(user.id)}
>
{user.name}
{`(${user.id})`}
</div>
);
})}
</div>
</div>
</div>
<div className="modal__footer">
<button onClick={this.closeModal}>Cancel</button>
<button onClick={this.saveList}>Save</button>
</div>
</div>
</Popup>
</>
);
}
}
export default Modal;
有人可以看一下,看看我在这里想念什么吗?另外,如果有更好的方法可以帮助我。
注意:目前,我没有为所选项目添加任何视觉体验。用户单击任何项目后,它将处于选中状态,并使用> or <
按钮可以移动项目。
答案 0 :(得分:1)
您的saveList
方法中的问题。 this.closeModal();
行将重置您的值。因此,您只需要更新open
状态。
请如下更新。
saveList = () => {
this.props.save(this.state.itemsLeft, this.state.itemsRight);
this.setState({ open: false });
};
答案 1 :(得分:1)
状态更新是异步的。按下保存按钮时,您会使用当前值更新父状态,然后还会使用通过仍然是旧状态的道具传递的状态更新模态。
答案 2 :(得分:0)
问题来自saveList函数。
当您致电this.props.save
时,它将在您的setState
父母中执行Sample
。
setState()是异步的,即使您使用prop调用closeModal,也不会在此时用“ good”值更新prop。
尝试在 openModal()中设置itemLefts
和itemsRight
openModal = () => {
this.setState({
open: true,
itemsLeft: this.props.usersUn,
itemsRight: this.props.usersSel
});
};
closeModal = () => {
this.setState({
open: false
});
};