Как управлять фильтрацией по флажкам с помощью React?
Я работаю над своим первым приложением React. Это приложение типа рецепт. Имеет фильтр ингредиентов. Основным компонентом является компонент Cookbook. Он имеет компонент "Фильтр" и компонент "Рецепт".
Компонент Recipe отображает все рецепты под нагрузкой. Компонент "Фильтр" отображает все необходимые ингредиенты или скобы. Эта часть все прекрасно работает.
Что я хочу сделать сейчас, так это когда человек нажимает на скобу, скажем, на сливочное масло, тогда он фильтрует весь список рецептов. Я предполагаю, что мне нужно передать состояние фильтра. Как я могу сделать это с этими флажками?
Вот что у меня есть:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
var data = require('./recipes.json');
function IngredientDetailList(props){
const ingredientList = props.ingredientList;
const listItems = ingredientList.map((ingredient, index) =>
<div key={index}>
{ingredient.measurement_amount}
{ingredient.measurement_unit}
{ingredient.ingredient}
</div>
);
return (
<div>{listItems}</div>
)
}
function Recipe(props){
const recipeList = props.cookbook.recipes
const listItems = recipeList.map((recipe) =>
<div key={recipe.id}>
<h2>{recipe.name}</h2>
<IngredientDetailList ingredientList = {recipe.ingredient_list}/>
</div>
);
return(
<div>{listItems}</div>
)
}
class Filter extends React.Component {
constructor(){
super();
this.state = {
checkedStaples: {},
}
}
render(){
const stapleList = this.props.stapleList;
const checkboxItems = stapleList.map((staple, index) =>
<div key = {index}>
<label>
<input type="checkbox" value="{staple}"/>
{staple}
</label>
</div>
);
return (
<form>
{checkboxItems}
</form>
);
}
}
class Cookbook extends React.Component {
constructor(){
super();
this.state ={
cookbook: data
}
}
getStapleList(recipes){
let stapleList = [];
recipes.forEach(function(recipe){
recipe.ingredient_list.forEach(function(list){
stapleList.push(list.needed_staple);
});
});
let flattenedStapleList = stapleList.reduce(function(a,b){
return a.concat(b);
})
return flattenedStapleList
}
render(){
const cookbook = this.state.cookbook;
const stapleList = this.getStapleList(cookbook.recipes);
return(
<div className="cookbook">
<div className="filter-section">
<h1>This is the filter section</h1>
<Filter stapleList = {stapleList}/>
</div>
<div className="recipes">
<h1>This is where the recipes go</h1>
<div className="recipe">
<Recipe cookbook = {cookbook}/>
</div>
</div>
</div>
);
}
}
ReactDOM.render(
<Cookbook />,
document.getElementById('root')
);
1 ответ
Вы можете попробовать сделать что-то вроде этого:
// ....
function Recipe(props){
const selectedStaples = props.selectedStaples;
const recipeList = props.cookbook.recipes
const listItems = recipeList.map((recipe) => {
const hasStaple = ingredient_list.reduce(
(_hasStaple, staple) => _hasStaple || selectedStaples.includes(staple),
false
);
// only show recipe if it has a staple
if (selectedStaples.length === 0 || hasStaple)
return (
<div key={recipe.id}>
<h2>{recipe.name}</h2>
<IngredientDetailList ingredientList = {recipe.ingredient_list}/>
</div>
);
}
return null;
}
);
return(
<div>{listItems}</div>
)
}
class Filter extends React.Component {
constructor(){
super();
this.state = {
checkedStaples: {},
}
}
render(){
const stapleList = this.props.stapleList;
const checkboxItems = stapleList.map((staple, index) =>
<div key = {index}>
<label>
<input
type="checkbox"
value="{staple}"
onClick={e => this.props.onChange(staple, e.checked)}
/>
{staple}
</label>
</div>
);
return (
<form>
{checkboxItems}
</form>
);
}
}
class Cookbook extends React.Component {
constructor(){
super();
this.state ={
cookbook: data,
selectedStaples: []
}
}
getStapleList(recipes){
let stapleList = [];
recipes.forEach(function(recipe){
recipe.ingredient_list.forEach(function(list){
stapleList.push(list.needed_staple);
});
});
let flattenedStapleList = stapleList.reduce(function(a,b){
return a.concat(b);
})
return flattenedStapleList
}
handleOnChange(staple, isChecked) {
const selectedStaples = this.state.selectedStaples;
if (isChecked) {
this.setState({
selectedStaples: selectedStaples.push(staple);
})
} else {
this.setState({
selectedStaples: selectedStaples.filter(selectedStaple => selectedStaple !== staple);
})
}
}
render(){
const selectedStaples = this.state.selectedStaples;
const cookbook = this.state.cookbook;
const stapleList = this.getStapleList(cookbook.recipes);
return(
<div className="cookbook">
<div className="filter-section">
<h1>This is the filter section</h1>
<Filter stapleList = {stapleList} onChange={this.handleOnChange.bind(this)}/>
</div>
<div className="recipes">
<h1>This is where the recipes go</h1>
<div className="recipe">
<Recipe cookbook = {cookbook} selectedStaples={selectedStaples} />
</div>
</div>
</div>
);
}
}
ReactDOM.render(
<Cookbook />,
document.getElementById('root')
);
Он отслеживает выбранные скрепки в компоненте поваренной книги и передает их в рецепт