簡體   English   中英

使用復選框反應嵌套組件

[英]React nested components with checkboxes

我有一個網站,其中包含十幾個組件。

每個父組件包含大約5個其他組件。 每個5個組件都包含一個表單。
父組件具有3個復選框。

1:展開該優惠中的所有組件(全部展開),
2:分配該組件中的所有內容(全部分配),
3:擴展組件(擴展產品)。

每個子組件都有兩個復選框。

1:展開組件(也展開產品),
2:分配組件中的所有內容(也分配所有內容)。

所有這些選項均適用於狀態更改。 它們都正常工作。 問題是,當我單擊“父”復選框時,無法取消選擇子級的單個組件。 因此,我無法取消選中子級組件內的復選框(子級擴展產品或子級全部分配)

封閉組件
在父級上擴展產品
在父級中擴展產品,在子級中擴展產品
在父級中展開全部,觸發在父級中展開產品,並觸發在子級組件中展開產品

這是渲染父組件的第一個文件:

 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;

我將不勝感激

如果為true ,則assign_all CountryOffer會覆蓋CountryOffer任何本地狀態

checked={assign_all ? assign_all : ...

這是沒有單一真相來源的問題。 我將重構您的代碼,以使CountryOffer是無狀態組件,並將所有狀態保留在父Offer組件中。

或者,將共享狀態的管理完全從組件中刪除。 (例如與react context ,redux,rxjs一起使用)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM