我正在使用React来显示我想按类别过滤的书名。单击类别名称旁边的复选框后,我希望对标题进行过滤。我没有使用提交按钮。
我对React还是有些陌生,并且阅读了有关“提升状态”的文档,但是我无法使其正常工作。我尚未阅读Hooks或Context API文档。也许这就是解决方案,但看来我正在做的事情还不够复杂……也许不是吗?
class Checkbox extends Component {
state = {
checked: false
}
handleClick = (e) => {
this.setState(() => ({ checked: !this.state.checked }))
}
render() {
const name = this.props.name;
return (
<label className="form__group">
<input type="checkbox" checked={this.state.checked} onChange={this.handleClick} className="form__input" />
<span className="form__faux-input"></span>
<span className="form__label">{name}</span>
</label>
)
}
}
function Sidebar({ categories }) {
return (
<div className="sidebar">
<div className="controls">
<div className="filter">
<h2 className="filter__heading">Filter By Category</h2>
<form className="filter-form">
{!categories
? <Spinner />
: categories.map((item) => (
<Checkbox key={item} name={item} />
))
}
<div className="form__group">
<button className="btn btn--rectangle btn--green">
<span className="btn-wrapper">Reset</span>
</button>
</div>
</form>
</div>
</div>
</div>
);
}
class App extends Component {
state = {
books: null,
categories: null
}
async componentDidMount() {
const { books, categories } = await getBooks();
this.setState(() => ({
books: books,
categories: categories
}));
}
render() {
const { books } = this.state;
const { categories } = this.state;
return (
<div className="App">
<Header />
<main className="main">
<div className="uiContainer">
<Sidebar
categories={categories}
/>
{!books
? <Spinner />
: <Card books={books} />
}
</div>
</main>
</div>
);
}
}
答案 0 :(得分:0)
我不是100%理解这个问题,但是如果您想像这样的部分
[x] cats
[x] dogs
[ ] rabbits // dont show rabbits
如果您不了解“提升状态”部分,则可以将选择和结果部分保留在一个react元素中
状态应包含这样的对象数组:
[{
allow: true,
title: 'cat'
},
{allow: false, title: 'rabbit'}]
要更新列表,请使用以下内容:
this.state.map(({title, allow}) => (
<div>
<TickBox onClick={() => this.toggleAnimal(title)} value={allow}/>
<p>{animalName}</p>
</div>
)
toggleAnimal函数应使用标题查找动物,并更新状态
然后您可以过滤掉所有不允许的动物
this.state
.filter(animal => animal.allowed)
.map(a => <p>{a.title}</p>)
此时,您有1个组件,渲染函数如下所示:
<h1>Please select the animals</h1>
{
animals.map(_ => <div><tickbox onClick={() => this.handleToggle(title)} /><title></div>)
}
<h1>Here are the filtered animals</h1>
{
animals.filter(a => a.allow).map(animal => animal.title).map(/* to JSX */)
}
如果根组件看起来像这样,则会更漂亮且响应更快:
render () {
<SelectAnimals toggle={handleToggle} animals={this.state} />
<ShowFilteredAnimals animals={this.state} />
}
handleToggle (title) {
this.setState(...)
}
可以看到,SelectAnimals通过调用props.toggle(以标题为参数)来获取一个函数作为参数,它可以与其父级进行通信
所以SelectAnimals看起来像这样:
props.animals.map(animal => (
<div>
<TickBox onClick=(() => {props.toggle(animal.title)}) /> // HERE
<p>{animal.title}</p>
</div>
))
因此,当勾号框触发click事件时,它将调用箭头功能。用标题调用props.toggle函数 在SelectAnimals的父级中,父元素将处理程序函数绑定到SelectAnimals.toggle,如下所示:
handleToggle (title) { // the child element called this function, it just got copied
}
PS:我在代码中进行了一些重命名,handleToggle函数可以与toggleAnimals相同
答案 1 :(得分:0)
假设列表呈现的位置是App
,则父组件Card
必须能够告诉Card
所选类别是什么。
为此,您可以:
1)在<App>
内创建一个回调函数:
_setCurrentCategory(selection) {
this.setState({currentCategory: selection})
}
2)将其作为道具传递给<Checkbox />
,并在onChange
中使用它:
class Checkbox extends Component {
render() {
const {name, setCurrentCategoryCallback } = this.props
return (
<label className="form__group">
<input
type="checkbox"
onChange={() => setCurrentCategoryCallback(name)}
className="form__input"
/>
<span className="form__faux-input"></span>
<span className="form__label">{name}</span>
</label>
)
}
}
..这将更改父级中的状态,以便您可以
2)然后将状态从<App />
传递到<Card />
:
<Card
currentCategory={this.state.currentCategory}
books={books}
/>
^^假定这是过滤列表将呈现的位置。在Card组件内部,您可以过滤/排序然后根据需要呈现列表,因为它现在同时具有书籍列表和当前选定的类别。
这是非常宽松的代码,但希望您能理解!
此外,在解构时,您不需要这样做:
const { books } = this.state;
const { categories } = this.state;
您可以改为:const { books, categories} = this.state
,因为它们都来自状态:)