我有一个切换下拉菜单的按钮。在此菜单中,用户可以切换复选框,应用更改或取消。
取消应将复选框重置为之前应用的更改。
我正在努力重置FilterMenu
组件的状态。我试图将初始状态字符串化,但事实证明这是有限的。
如何将FilterMenu
组件的状态重置为先前应用的更改?
当用户取消时:
过滤组件
//close menu and reset state
handleCancel() {
this.setState({menuOpen: false});
this.props.resetState();
}
调用 resetState
来解析我的初始状态并设置它。
主要组件
resetState() {
this.setState(JSON.parse(this.baseState));
}
const FilterMenu = ({checkBoxes, handleChange, handleCancel, handleSave}) => {
return (
<div>
{Object.keys(checkBoxes).map(key => {
return (
<div key={key}>
<label htmlFor={key}>{checkBoxes[key].name}</label>
<input
id={key}
type="checkbox"
checked={checkBoxes[key].isChecked}
onChange={handleChange}
/>
</div>
);
})}
<button onClick={handleCancel}>Cancel</button>
<button onClick={handleSave}>Save</button>
</div>
);
};
class Filter extends React.Component {
constructor(props) {
super(props);
this.state = {
menoOpen: false,
};
this.handleCancel = this.handleCancel.bind(this);
this.handleButtonClick = this.handleButtonClick.bind(this);
}
handleCancel() {
this.setState({menuOpen: false});
this.props.resetState();
}
handleButtonClick() {
this.setState({menuOpen: !this.state.menuOpen});
}
render() {
return (
<div>
<button onClick={this.handleButtonClick}>Choose Fruits</button>
{this.state.menuOpen && (
<FilterMenu
checkBoxes={this.props.checkBoxes}
handleSave={this.props.handleSave}
handleCancel={this.handleCancel}
handleChange={this.props.handleChange}
/>
)}
</div>
);
}
}
//Parent component
class Main extends React.Component {
constructor() {
super();
this.state = {
checkBoxes: {
1: {
name: 'Apple',
isChecked: true,
},
2: {
name: 'Pear',
isChecked: true,
},
3: {
name: 'Tomato',
isChecked: true,
},
},
fruit: {
1: {
name: 'Apple',
},
3: {
name: 'Apple',
},
4: {
name: 'Pear',
},
5: {
name: 'Tomato',
},
6: {
name: 'Apple',
},
},
checkedBoxes: [],
};
this.baseState = JSON.stringify(this.state);
this.fruitFilter = this.fruitFilter.bind(this);
this.handleSave = this.handleSave.bind(this);
this.handleChange = this.handleChange.bind(this);
this.resetState = this.resetState.bind(this);
}
resetState() {
this.setState(JSON.parse(this.baseState));
}
//populates the checkedboxs array with name to filter by
handleSave() {
//look at the checked boxes
//filter the fruit based on the ones that are checked`
const checkedBoxes = Object.keys(this.state.checkBoxes)
.filter(key => {
//return name of fruit if it is checked
return this.state.checkBoxes[key].isChecked
? this.state.checkBoxes[key].name
: false;
})
.reduce((a, b) => {
a.push(this.state.checkBoxes[b].name);
return a;
}, []);
console.log(checkedBoxes);
this.setState({checkedBoxes: checkedBoxes});
}
//handles the checkbox toggle
handleChange(e) {
const checkBoxes = {...this.state.checkBoxes};
checkBoxes[e.target.id].isChecked = e.target.checked;
this.setState({checkBoxes: checkBoxes});
}
//filteres the fruit - if nothing is checked return them all
fruitFilter(fruit) {
return Object.keys(fruit)
.filter(key => {
return (
this.state.checkedBoxes.length <= 0 ||
this.state.checkedBoxes.indexOf(fruit[key].name) > -1
);
})
.reduce((a, b) => {
a[b] = fruit[b];
return a;
}, {});
}
render() {
const visibleFruits = this.fruitFilter(this.state.fruit);
return (
<div>
<Filter
resetState={this.resetState}
checkBoxes={this.state.checkBoxes}
handleSave={this.handleSave}
handleChange={this.handleChange}
/>
<div>
<h2>Filtered Fruit</h2>
{Object.keys(visibleFruits).map(key => {
return (
<div key={key}>
<span>{visibleFruits[key].name}</span>
</div>
);
})}
</div>
</div>
);
}
}
ReactDOM.render(<Main />, document.getElementById('react'))
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
答案 0 :(得分:0)
问题是您在修改之前没有保存以前的状态。请记住,构造函数只被调用一次
我在handleSave
this.baseState = JSON.stringify(this.state.checkBoxes)
并在resetState
this.setState({checkBoxes: JSON.parse(this.baseState)});
以下是修改后的版本:
const FilterMenu = ({checkBoxes, handleChange, handleCancel, handleSave}) => {
return (
<div>
{Object.keys(checkBoxes).map(key => {
return (
<div key={key}>
<label htmlFor={key}>{checkBoxes[key].name}</label>
<input
id={key}
type="checkbox"
checked={checkBoxes[key].isChecked}
onChange={handleChange}
/>
</div>
);
})}
<button onClick={handleCancel}>Cancel</button>
<button onClick={handleSave}>Save</button>
</div>
);
};
class Filter extends React.Component {
constructor(props) {
super(props);
this.state = {
menoOpen: false,
};
this.handleCancel = this.handleCancel.bind(this);
this.handleButtonClick = this.handleButtonClick.bind(this);
}
handleCancel() {
// this.setState({menuOpen: false});
this.props.resetState();
}
handleButtonClick() {
this.setState({menuOpen: !this.state.menuOpen});
}
render() {
return (
<div>
<button onClick={this.handleButtonClick}>Choose Fruits</button>
{this.state.menuOpen && (
<FilterMenu
checkBoxes={this.props.checkBoxes}
handleSave={this.props.handleSave}
handleCancel={this.handleCancel}
handleChange={this.props.handleChange}
/>
)}
</div>
);
}
}
//Parent component
class Main extends React.Component {
constructor() {
super();
this.state = {
checkBoxes: {
1: {
name: 'Apple',
isChecked: true,
},
2: {
name: 'Pear',
isChecked: true,
},
3: {
name: 'Tomato',
isChecked: true,
},
},
fruit: {
1: {
name: 'Apple',
},
3: {
name: 'Apple',
},
4: {
name: 'Pear',
},
5: {
name: 'Tomato',
},
6: {
name: 'Apple',
},
},
checkedBoxes: ['Apple', 'Pear', 'Tomato'],
};
this.baseState = JSON.stringify(this.state.checkBoxes)
this.fruitFilter = this.fruitFilter.bind(this);
this.handleSave = this.handleSave.bind(this);
this.handleChange = this.handleChange.bind(this);
this.resetState = this.resetState.bind(this);
}
resetState() {
console.log(this.baseState)
this.setState({checkBoxes: JSON.parse(this.baseState)});
}
//populates the checkedboxs array with name to filter by
handleSave() {
//look at the checked boxes
//filter the fruit based on the ones that are checked`
this.baseState = JSON.stringify(this.state.checkBoxes)
const checkedBoxes = Object.keys(this.state.checkBoxes)
.filter(key => {
//return name of fruit if it is checked
return this.state.checkBoxes[key].isChecked
? this.state.checkBoxes[key].name
: false;
})
.reduce((a, b) => {
a.push(this.state.checkBoxes[b].name);
return a;
}, []);
console.log(checkedBoxes);
this.setState({checkedBoxes: checkedBoxes});
}
//handles the checkbox toggle
handleChange(e) {
const checkBoxes = {...this.state.checkBoxes};
checkBoxes[e.target.id].isChecked = e.target.checked;
this.setState({checkBoxes: checkBoxes});
}
//filteres the fruit - if nothing is checked return them all
fruitFilter(fruit) {
return Object.keys(fruit)
.filter(key => {
return (
this.state.checkedBoxes.length <= 0 ||
this.state.checkedBoxes.indexOf(fruit[key].name) > -1
);
})
.reduce((a, b) => {
a[b] = fruit[b];
return a;
}, {});
}
render() {
const visibleFruits = this.fruitFilter(this.state.fruit);
return (
<div>
<Filter
resetState={this.resetState}
checkBoxes={this.state.checkBoxes}
handleSave={this.handleSave}
handleChange={this.handleChange}
/>
<div>
<h2>Filtered Fruit</h2>
{Object.keys(visibleFruits).map(key => {
return (
<div key={key}>
<span>{visibleFruits[key].name}</span>
</div>
);
})}
</div>
</div>
);
}
}
ReactDOM.render(<Main />, document.getElementById('react'))
&#13;
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
&#13;
请注意,由于性能问题,不建议使用JSON.stringify
克隆对象,对于实际应用程序,您应该使用正确的深度克隆方法(来自库或您自己的实现)