我正在尝试为一组过滤器动态生成一个状态属性。这些过滤器包含不同的复选框“名称”和“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 };
});
答案 0 :(得分:0)
您正在设置被禁止的状态内部人 render()。相反,调用一个函数,检查状态是否与您想要的不同,如果是,则更新它。如果不是 - 从函数返回并且不改变状态。