有人可以解释为什么多次调用 useEffect 钩子(如下面的代码)会导致陈旧状态?
imports ...
function App () {
const classes = useStyles()
const [formState, setFormState] = useState({
ageLevel: '',
schoolGrade: '',
booksCategories: '',
numTitle: '',
titleTypes: '',
materialType: '',
subjInterest: '',
pastBook: '',
numOfBags: '',
bag1: '',
bag2: '',
})
const handleTxtFldChange = (e, name) => {
setFormState({ ...formState, [name]: e.target.value })
}
useEffect(() => {
if (formState.ageLevel !== 'Adults') {
setFormState({
...formState,
numTitle: '',
materialType: '',
subjInterest: '',
pastBook: ''
})
}
}, [formState.ageLevel])
useEffect(() => {
if (formState.ageLevel !== 'Toddlers' || formState.ageLevel !== 'Preschoolers') {
setFormState({
...formState,
numOfBags: '',
bag1: '',
bag2: ''
})
}
}, [formState.ageLevel])
useEffect(() => {
if (formState.ageLevel !== 'School-Age') {
setFormState({
...formState,
schoolGrade: '',
booksCategories: ''
})
}
}, [formState.ageLevel])
useEffect(() => {
if (formState.ageLevel !== 'Teens') {
setFormState({
...formState,
titleTypes: '',
subjInterest: '',
pastBook: ''
})
}
}, [formState.ageLevel])
return (
<>
<div className='App'>
<Container>
<AgeLevelSelect
formState={formState}
setFormState={setFormState}
/>
<GradeSelect
formState={formState}
setFormState={setFormState}
/>
<BooksCategories
formState={formState}
setFormState={setFormState}
/>
<NumTitles
formState={formState}
setFormState={setFormState}
ageLevel={formState.ageLevel}
/>
<TypeOfTitles
formState={formState}
setFormState={setFormState}
ageLevel={formState.ageLevel}
location={formState.location}
/>
<TypeOfMaterial
formState={formState}
setFormState={setFormState}
ageLevel={formState.ageLevel}
/>
<SubjOfInterest
formState={formState}
setFormState={setFormState}
ageLevel={formState.ageLevel}
materialType={formState.materialType}
/>
<PastBook
formState={formState}
setFormState={setFormState}
ageLevel={formState.ageLevel}
materialType={formState.materialType}
/>
<NumOfBag
formState={formState}
setFormState={setFormState}
ageLevel={formState.ageLevel}
/>
<Bag1
formState={formState}
setFormState={setFormState}
numOfBags={formState.numBookBags}
/>
<Bag2
formState={formState}
setFormState={setFormState}
numOfBags={formState.numBookBags}
/>
</form>
</Container>
</div>
</>
)
}
export default App
任何想法,我做错了什么?
我想要实现的只是在用户切换表单中的关闭和打开问题时重置部分状态,但显然,我缺少一些基本的反应概念。
答案 0 :(得分:1)
这是因为 formState
未包含在 useEffect
的依赖项数组中,而是用于 useEffect
中。
但是,如果您将其添加到 useEffect
的依赖项数组中,您将收到一个无限循环。
为了解决这个问题,你可以使用 setState
的回调语法,不要求它在依赖数组中但仍然接收当前值。
function App () {
const classes = useStyles()
const [formState, setFormState] = useState({
ageLevel: '',
schoolGrade: '',
booksCategories: '',
numTitle: '',
titleTypes: '',
materialType: '',
subjInterest: '',
pastBook: '',
numOfBags: '',
bag1: '',
bag2: '',
})
const handleTxtFldChange = (e, name) => {
setFormState({ ...formState, [name]: e.target.value })
}
useEffect(() => {
setFormState(currentState => {
const newState = { ...currentState };
if (formState.ageLevel !== 'Adults') {
newState.numTitle = '';
newState.materialType = '';
newState.subjInterest = '';
newState.pastBook = ''
}
if (formState.ageLevel !== 'Toddlers' && formState.ageLevel !== 'Preschoolers') {
newState.numOfBags = '';
newState.bag1 = '';
newState.bag2 = '';
}
if (formState.ageLevel !== 'Teens') {
newState.titleTypes = '';
newState.subjInterest = '';
newState.pastBook = '';
}
return newState;
});
}, [formState.ageLevel]);
return (
<>
<div className='App'>
<Container>
<AgeLevelSelect
formState={formState}
setFormState={setFormState}
/>
<GradeSelect
formState={formState}
setFormState={setFormState}
/>
<BooksCategories
formState={formState}
setFormState={setFormState}
/>
<NumTitles
formState={formState}
setFormState={setFormState}
ageLevel={formState.ageLevel}
/>
<TypeOfTitles
formState={formState}
setFormState={setFormState}
ageLevel={formState.ageLevel}
location={formState.location}
/>
<TypeOfMaterial
formState={formState}
setFormState={setFormState}
ageLevel={formState.ageLevel}
/>
<SubjOfInterest
formState={formState}
setFormState={setFormState}
ageLevel={formState.ageLevel}
materialType={formState.materialType}
/>
<PastBook
formState={formState}
setFormState={setFormState}
ageLevel={formState.ageLevel}
materialType={formState.materialType}
/>
<NumOfBag
formState={formState}
setFormState={setFormState}
ageLevel={formState.ageLevel}
/>
<Bag1
formState={formState}
setFormState={setFormState}
numOfBags={formState.numBookBags}
/>
<Bag2
formState={formState}
setFormState={setFormState}
numOfBags={formState.numBookBags}
/>
</form>
</Container>
</div>
</>
)
}
export default App
注意:我假设 if (formState.ageLevel !== 'Toddlers' || formState.ageLevel !== 'Preschoolers')
应该是 if (formState.ageLevel !== 'Toddlers' && formState.ageLevel !== 'Preschoolers')
否则它总是会评估为真。