Я создаю компонент реагирования, в котором пользователи могут выбирать между вариантами, и как только пользователь нажимает сохранить после выбора, я сохраняю параметры в состоянии. Тем не менее, он не сохраняется после первого нажатия кнопки сохранения (который находится внутри модального). Как только я закрываю модальное и снова открываю, сохраняются последние выбранные опции.
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;
Может кто-нибудь посмотреть и посмотреть, что мне здесь не хватает? Кроме того, это помогает мне, если есть какой-нибудь лучший способ сделать это.
Codesandbox
Примечание: В настоящее время я не добавил визуальный опыт для выбранного элемента. Когда пользователь нажимает на любой элемент, он будет выбран, и с помощью кнопок > or <
пользователь сможет перемещать элементы.