无法保存第一次点击的状态
Unable to save state for first click
我正在构建一个反应组件,用户可以在其中选择选项,一旦用户在选择后点击保存,我就会将选项保存在状态中。但是,在第一次单击保存(在模态内)后,它并没有被保存。一旦我关闭模式并再次打开,最后选择的选项就会被保存。
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 <
按钮用户可以移动项目。
您的 saveList
方法存在问题。 this.closeModal();
行将重置您的值。所以你只需要更新 open
状态。
请更新如下。
saveList = () => {
this.props.save(this.state.itemsLeft, this.state.itemsRight);
this.setState({ open: false });
};
这是为您准备的工作演示 https://codesandbox.io/s/react-multi-select-olqc9。
问题出在 saveList 函数上。
当您调用 this.props.save
时,它将在您的 Sample
父级中执行 setState
。
setState() 是 异步的 ,即使你用 props 调用 closeModal,此时 props 也不会用 'good' 值更新。
尝试在 openModal() 中设置 itemLefts
和 itemsRight
openModal = () => {
this.setState({
open: true,
itemsLeft: this.props.usersUn,
itemsRight: this.props.usersSel
});
};
closeModal = () => {
this.setState({
open: false
});
};
状态更新是异步的。当按下保存时,您会使用当前值更新父状态,但也会使用您通过 props 传递的内容更新模态状态,仍然是旧状态。
我正在构建一个反应组件,用户可以在其中选择选项,一旦用户在选择后点击保存,我就会将选项保存在状态中。但是,在第一次单击保存(在模态内)后,它并没有被保存。一旦我关闭模式并再次打开,最后选择的选项就会被保存。
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 <
按钮用户可以移动项目。
您的 saveList
方法存在问题。 this.closeModal();
行将重置您的值。所以你只需要更新 open
状态。
请更新如下。
saveList = () => {
this.props.save(this.state.itemsLeft, this.state.itemsRight);
this.setState({ open: false });
};
这是为您准备的工作演示 https://codesandbox.io/s/react-multi-select-olqc9。
问题出在 saveList 函数上。
当您调用 this.props.save
时,它将在您的 Sample
父级中执行 setState
。
setState() 是 异步的 ,即使你用 props 调用 closeModal,此时 props 也不会用 'good' 值更新。
尝试在 openModal() 中设置 itemLefts
和 itemsRight
openModal = () => {
this.setState({
open: true,
itemsLeft: this.props.usersUn,
itemsRight: this.props.usersSel
});
};
closeModal = () => {
this.setState({
open: false
});
};
状态更新是异步的。当按下保存时,您会使用当前值更新父状态,但也会使用您通过 props 传递的内容更新模态状态,仍然是旧状态。