如何使用React管理复选框过滤?

时间:2017-07-29 14:22:07

标签: forms reactjs checkbox

我正在开发我的第一个React应用程序。这是一种配方应用程序。它有一个成分过滤器。主要组件是Cookbook组件。它有一个Filter组件和一个Recipe组件。

Recipe组件显示加载时的所有配方。过滤器组件显示所有需要的成分或主食。这一部分都很棒。

我现在要做的是当一个人点击一个主食时,让我们说黄油,它会过滤整个食谱清单。我的假设是我需要通过Filter的状态。如何使用这些复选框执行此操作?

这就是我所拥有的:

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}&nbsp;
            {ingredient.measurement_unit}&nbsp;
            {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 个答案:

答案 0 :(得分: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')
);

它跟踪cookbook组件中的选定镫骨并将其传递给配方