使用复选框反应嵌套组件

时间:2018-08-10 11:46:08

标签: javascript reactjs

我有一个网站,其中包含十几个组件。

每个父组件都包含大约5个其他组件。每个5个组件都包含一个表单。
父组件具有3个复选框。

1:扩展该商品中的所有组件(全部扩展),
2:分配该组件中的所有组件(全部分配),
3:扩展该组件(扩展产品) 。

每个子组件都有两个复选框。

1:扩展组件(也扩展产品),
2:分配组件中的所有内容(也分配所有内容) )。

所有这些选项都可用于状态更改。它们都正常工作。问题是,当我单击“父”复选框时,无法取消选择子级的单个组件。因此,我不能取消选中子组件(孩子的扩展产品或孩子的全部分配)中的复选框

closed components
expand product on parent
expand product in parent, expand product in child
expand all in parent,triggers expand product in parent and it triggers expand product in childs component

这是渲染父组件的第一个文件:

 class Offer extends React.Component {
 constructor(props){
    super(props);

    this.state = {
        checkedItems: new Map()
    };

    this.handleChange = this.handleChange.bind(this);
}

handleChange(e) {
    const item = e.target.name;
    const isChecked = e.target.checked;

    this.setState(prevState => ({
        checkedItems: prevState.checkedItems.set(item, isChecked)
    }));
}

render(){
    const { data, country_offer, country_offer_tab, countries, } = this.props;

    return (
        <div className="offer-wrapper">
            <div className={"offer-header " + data[2] }>
                <div>
                    <div className="custom_checkbox">
                        <div className="custom_checkbox">
                            <input
                                type={"checkbox"}
                                name={`${data[2]}_expand_all`}
                                className="expand_all"
                                checked={this.state.checkedItems.get(`${data[2]}_expand_all`) || false}
                                onChange={this.handleChange}
                                id={`${data[2]}_expand_all`}
                            />
                            <label htmlFor={`${data[2]}_expand_all`}>Expand all</label>
                        </div>
                        <div className="custom_checkbox">
                            <input
                                type={"checkbox"}
                                name={`${data[2]}_assign_all`}
                                className="assign_all"
                                checked={this.state.checkedItems.get(`${data[2]}_assign_all`) || false}
                                onChange={this.handleChange}
                                id={`${data[2]}_assign_all`}
                            />
                            <label htmlFor={`${data[2]}_assign_all`}>Assign all products</label>
                        </div>
                        <div className="custom_checkbox">
                            <input
                                type={"checkbox"}
                                name={`${data[2]}_expand_product`}
                                className="expand_product"
                                checked={( this.state.checkedItems.get(`${data[2]}_expand_product`) || this.state.checkedItems.get(`${data[2]}_expand_all`) ) || false}
                                onChange={this.handleChange}
                                id={`${data[2]}_expand_product`}
                            />
                            <label htmlFor={`${data[2]}_expand_product`}>Expand product</label>
                        </div>
                    </div>
                </div>
            </div>

            {
                (this.state.checkedItems.get(`${data[2]}_expand_all`) || this.state.checkedItems.get(`${data[2]}`+'_expand_product'))  &&
                    <CountryOffer
                        country_offer_tab={country_offer_tab}
                        countries={countries}
                        data={data}
                        expand_all={this.state.checkedItems.get(`${data[2]}_expand_all`)}
                        expand_product={this.state.checkedItems.get(`${data[2]}_expand_product`)}
                        assign_all={this.state.checkedItems.get(`${data[2]}_assign_all`)}
                    />
            }
        </div>
    )
}
}

export default Offer;

这是子组件

class CountryOffer extends React.Component{
constructor(props){
    super(props);

    this.state = {
        checkedItems: new Map(),
    };

    this.handleChange = this.handleChange.bind(this);
}

handleChange(e) {
    if (!this.props.expand_all){
        const item = e.target.name;
        const isChecked = e.target.checked;

        this.setState(prevState => ({
            checkedItems: prevState.checkedItems.set(item, isChecked)
        }));
    } else {
        console.log('cant uncheck/check this')
    }
}

render(){
    const { country_offer_tab, countries, data, expand_all, expand_product, assign_all} = this.props;
    return (
        <div className={"offer-details " + data[2]}>
            {country_offer_tab[data[2]].map((country, k) => {
                return (
                    <div key={k}>
                        <div className="offer-country-header" >
                            <div>
                                <span className={"iti-flag "+(countries[k].symbol).toLowerCase()}/>
                                <span>{countries[k].name}</span>
                            </div>
                            <div className='custom_checkbox'>
                                <input
                                    checked={assign_all ? assign_all : (this.state.checkedItems.get(`intersections_for ${data[2]}|${countries[k].id}`) || false)} onChange={this.handleChange}
                                    type="checkbox"
                                    name={"intersections_for "+ data[2] + '|' + countries[k].id}
                                    id={"intersections_for "+ data[2] + '|' + countries[k].id}/>
                                <label className="intersections_group_label" htmlFor={"intersections_for "+ data[2] + '|' + countries[k].id}>Check/uncheck all</label>
                            </div>
                            <div className='custom_checkbox'>
                                <input
                                    checked={expand_all ? expand_all : (this.state.checkedItems.get(`expand_geo ${data[2]}|${countries[k].id}`) || false)} onChange={this.handleChange}
                                    type="checkbox"
                                    name={"expand_geo " + data[2] + '|' + countries[k].id}
                                    id={"expand_geo " + data[2] + '|' + countries[k].id}/>
                                <label htmlFor={"expand_geo "+ data[2] + '|' + countries[k].id}>Expand GEO</label>
                            </div>
                        </div>

                        {
                            (expand_all || this.state.checkedItems.get(`expand_geo ${data[2]}|${countries[k].id}`)) &&
                                <CountryOfferIntersections
                                    country_offer_tab={country_offer_tab}
                                    offer_id={data[2]}
                                    country_id={countries[k].id}
                                    check_all={this.state.checkedItems.get(`intersections_for ${data[2]}|${countries[k].id}`)}
                                    assign_all={assign_all}
                                    expand_product={expand_product}
                                />
                        }
                    </div>
                )
            })}
        </div>
    )}
}

 export default CountryOffer;

我将不胜感激

1 个答案:

答案 0 :(得分:0)

如果true,则assign_all道具将覆盖CountryOffer中的任何本地状态

checked={assign_all ? assign_all : ...

这是没有单一真相来源的问题。我将重构您的代码,以使CountryOffer是无状态组件,并将所有状态保留在父Offer组件中。

或者,将共享状态的管理完全从组件中删除。 (例如,使用react context,redux,rxjs)