[英]Updating the state for checkboxes Inputs dynamically
I'm trying to generate a state property dynamically for an array of filters.我正在尝试为过滤器数组动态生成 state 属性。 These filters contain different checkboxes "names" and "isChecked" for each.这些过滤器分别包含不同的复选框“名称”和“isChecked”。 See below example:请参阅以下示例:
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}...
Note: There are around 140 in total.注:总共约有 140 个。
To get to this list I'm filtering a list I'm fetching from a server thus, I can filter duplicates and map it correctly.为了获得此列表,我正在过滤从服务器获取的列表,因此,我可以正确过滤重复项和 map。 All of this happens in the render method.所有这些都发生在 render 方法中。
Also, see the initial state. The property I need to update is "filter":另外,请参阅初始 state。我需要更新的属性是“过滤器”:
state = {
dogFilter: '',
formIsOpen: false,
advancedFilterRequested: false,
filters: [],
};
Inside the render method, I'm calling a method from my class that is supposed to update the "filters" property from the state. See below:在渲染方法中,我从我的 class 调用一个方法,该方法应该更新 state 的“过滤器”属性。见下文:
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>
);
}
Im getting the following error我收到以下错误
Error: Maximum update depth exceeded.错误:超出最大更新深度。 This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate.当组件在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState 时,就会发生这种情况。 React limits the number of nested updates to prevent infinite loops. React 限制嵌套更新的数量以防止无限循环。
Is there a different way to update the state here.有没有不同的方法来更新 state 在这里。 I'm new to react so not sure what to do next.我是新手,所以不确定下一步该怎么做。 I tried using componentDidMounth but I get the same error.我尝试使用 componentDidMounth 但我得到了同样的错误。
UPDATE: I have done this and it seemed to work:更新:我已经这样做了,它似乎有效:
componentDidUpdate() {
this.updateFiltersHandler();
}
updateFiltersHandler = () => {
if (this.filtersForIntialState.length === this.state.filters.length) {
return;
} else {
this.setState({ filters: this.filtersForIntialState });
}
};
Also, I replace this from my previous code:另外,我用我以前的代码替换了它:
const filtersForIntialState = filterBreedFor
.concat(
mainTemperamentsFiltersNoDuplicates,
advancedTemperamentFiltersNoDuplicates
)
.map((filter) => {
return { name: filter, isChecked: false };
});
this.updateFiltersHandler(filtersForIntialState);
with this:有了这个:
this.filtersForIntialState = filterBreedFor
.concat(
mainTemperamentsFiltersNoDuplicates,
advancedTemperamentFiltersNoDuplicates
)
.map((filter) => {
return { name: filter, isChecked: false };
});
You are setting the state insider render() which is forbidden.您正在设置 state insider render() 这是被禁止的。 Instead, call a function, check if the state is different than what you want it to be, and if so, update it.相反,请拨打 function,检查 state 是否与您想要的不同,如果不同,请更新它。 If not - return from function and don't change the state.如果不是 - 从 function 返回并且不要更改 state。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.