动态更新复选框输入的状态

时间:2021-01-14 10:27:43

标签: javascript reactjs react-native

我正在尝试为一组过滤器动态生成一个状态属性。这些过滤器包含不同的复选框“名称”和“isChecked”。见下例:

0: {name: "accompanying", isChecked: false}
1: {name: "bolting", isChecked: false}
2: {name: "carrying", isChecked: false}
3: {name: "coursing", isChecked: false}
4: {name: "defending", isChecked: false}
5: {name: "droving", isChecked: false}... 

注意:总共有大约 140 个。

为了进入这个列表,我正在过滤我从服务器获取的列表,因此,我可以过滤重复项并正确映射它。所有这些都发生在 render 方法中。

另外,查看初始状态。我需要更新的属性是“过滤器”:

    state = {
        dogFilter: '',
        formIsOpen: false,
        advancedFilterRequested: false,
        filters: [],
    };

在 render 方法中,我从我的类中调用一个方法,该方法应该从状态更新“过滤器”属性。见下文:

updateFiltersHandler = (filters) => {
    this.setState({ filters: filters });
};
render() {
        let breedForFilters;
        let temperamentMainFilters;
        let temperamentAdvancedFilter;
         
        //data coming from the reducer  
        if (this.props.dogs) {
            const initialDogsBreedForFilter = this.props.dogs
                .map((dog) => dog.bred_for)
                .join(' , ')
                .split(' ')
                .filter((word) => {
                    return word.endsWith('ing');
                })
                .map((word) => word.toLowerCase())
                .filter((word) => word !== 'driving')
                .sort();

            const dogsBreedWithoutDuplicates = removeDublicates(
                initialDogsBreedForFilter
            );

            // filters data before allocating it to elements TEMPERAMENT

            const initialTemperamentFilter = this.props.dogs
                .map((dog) => dog.temperament)
                .join(' , ')
                .split(' ')
                .filter((word) => word.length > 3)
                .map((word) => word.replace(',', '').toLowerCase())
                .sort();

            // SPLITS MAIN AND ADVANCED FILTERS IN TEMPERAMENT

            const advancedTemperamentFilters = initialTemperamentFilter.filter(
                (word) =>
                    word !== 'stubborn' &&
                    word !== 'playful' &&
                    word !== 'active' &&
                    word !== 'friendly' &&
                    word !== 'intelligent' &&
                    word !== 'gentle' &&
                    word !== 'gay'
            );

            const mainTemperamentsFilters = initialTemperamentFilter.filter(
                (word) =>
                    word === 'stubborn' ||
                    word === 'playful' ||
                    word === 'active' ||
                    word === 'friendly' ||
                    word === 'intelligent' ||
                    word === 'gentle'
            );

            //REMOVES DUPLICATES FROM MAIN LIST USING A HELPER FUNCTION 

            const mainTemperamentsFiltersNoDuplicates = removeDublicates(
                mainTemperamentsFilters
            );

            const advancedTemperamentFiltersNoDuplicates = removeDublicates(
                advancedTemperamentFilters
            );

            // Sets state for Filters CheckBoxes: => here is where I need help! 

            const filterBreedFor = dogsBreedWithoutDuplicates;

            const filtersForIntialState = filterBreedFor
                .concat(
                    mainTemperamentsFiltersNoDuplicates,
                    advancedTemperamentFiltersNoDuplicates
                )
                .map((filter) => {
                    return { name: filter, isChecked: false };
                });

            this.updateFiltersHandler(filtersForIntialState); 

            //BUILDS RENDER ELEMENTS

            breedForFilters = filterBuilder(
                'breedForFilter',
                dogsBreedWithoutDuplicates,
                this.onChangeCheckboxHandler
            );

            temperamentMainFilters = filterBuilder(
                'temperament',
                mainTemperamentsFiltersNoDuplicates,
                this.onChangeCheckboxHandler
            );

            temperamentAdvancedFilter = filterBuilder(
                'temperament',
                advancedTemperamentFiltersNoDuplicates,
                this.onChangeCheckboxHandler
            );
        }

        // CLASSES

        let formClass = [styles.FormHolder];
        if (this.state.formIsOpen) {
            formClass = [styles.FormHolder, styles.ShowForm];
        }

        let advancedFilterClass = [styles.OptionsHolderAdvanced];

        if (this.state.advancedFilterRequested) {
            advancedFilterClass = [styles.OptionsHolderAdvanced, styles.Show];
        }
        return (
            <React.Fragment>
                <MainNavbar />
                <header className={styles.FindADogFiltersSection}>
                    <h2>find your perfect puppy</h2>
                    <SectionDivider />
                    <div className={styles.FidDogFiltersHolder}>
                        <div className={styles.FilterBtn} onClick={this.openFormHandler}>
                            filters
                        </div>
                    </div>
                    <form className={formClass.join(' ')}>
                        <header className={styles.FormHeader}>
                            <FontAwesomeIcon
                                icon={faTimes}
                                className={styles.CloseFilterSectionBtn}
                                onClick={this.closeFormHandler}
                            />
                            <h2> filters </h2>
                            <button
                                className={styles.ClearSearch}
                                onClick={(event) => {
                                    event.preventDefault();
                                    this.clearFiltersHandler();
                                }}
                            >
                                clear
                            </button>
                        </header>
                        <div className={styles.OptionsSection}>
                            <div className={styles.CategoriesHolder}>
                                <h3>breed for</h3>
                                <div className={styles.OptionsHolder}>{breedForFilters}</div>
                            </div>

                            <div className={styles.CategoriesHolder}>
                                <h3>temperament</h3>
                                <div className={styles.OptionsHolder}>
                                    {temperamentMainFilters}
                                </div>
                                <div className={styles.AdvanceFiltersBtnHolder}>
                                    <button
                                        onClick={(event) => {
                                            event.preventDefault();
                                            this.openandCloseAdvancedSearch();
                                        }}
                                    >
                                        advanced
                                    </button>
                                </div>
                                <div className={advancedFilterClass.join(' ')}>
                                    {temperamentAdvancedFilter}
                                </div>
                            </div>
                            <div className={styles.CategoriesHolder}>
                                <h3>Size</h3>
                                <div className={styles.OptionsHolder}>
                                    <div key="small">
                                        <input type="checkbox" name="breedFor" value="35" />
                                        <label>Small</label>
                                    </div>
                                    <div key="big">
                                        <input type="checkbox" name="breedFor" value="36" />
                                        <label>Big</label>
                                    </div>
                                </div>
                            </div>
                            <div className={styles.SearchBtnHolder}>
                                <button
                                    className={styles.SearchBtn}
                                    onClick={(event) => {
                                        event.preventDefault();
                                        this.searchRequestHandler();
                                        this.setState({ advancedFilterRequested: false });
                                    }}
                                >
                                    search
                                </button>
                            </div>
                        </div>
                    </form>
                </header>
                <FinderDisplayDogs data={this.props.dogs} />
                <MainFooter />
            </React.Fragment>
        );
    }

我收到以下错误

错误:超出最大更新深度。当组件在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState 时,就会发生这种情况。 React 限制嵌套更新的数量以防止无限循环。

这里是否有不同的方式来更新状态。我是新手,所以不知道下一步该怎么做。我尝试使用 componentDidMounth 但我得到了同样的错误。

更新:我已经这样做了,它似乎有效:

    componentDidUpdate() {
        this.updateFiltersHandler();
    }

    updateFiltersHandler = () => {
        if (this.filtersForIntialState.length === this.state.filters.length) {
            return;
        } else {
            this.setState({ filters: this.filtersForIntialState });
        }
    };

另外,我从我以前的代码中替换了这个:

            const filtersForIntialState = filterBreedFor
                .concat(
                    mainTemperamentsFiltersNoDuplicates,
                    advancedTemperamentFiltersNoDuplicates
                )
                .map((filter) => {
                    return { name: filter, isChecked: false };
                });

            this.updateFiltersHandler(filtersForIntialState); 

这样:

            this.filtersForIntialState = filterBreedFor
                .concat(
                    mainTemperamentsFiltersNoDuplicates,
                    advancedTemperamentFiltersNoDuplicates
                )
                .map((filter) => {
                    return { name: filter, isChecked: false };
                });

1 个答案:

答案 0 :(得分:0)

您正在设置被禁止的状态内部人 render()。相反,调用一个函数,检查状态是否与您想要的不同,如果是,则更新它。如果不是 - 从函数返回并且不改变状态。

相关问题