如何解决在初始渲染时调用useEffect挂钩,而无需更改依赖项
好的,我遇到了一些我不太了解的行为。 我有这个useState钩子
const [permanent,setPermanent] = useState(false)
和这个useEffect钩子
useEffect(() => {
if (permanent) {
dispatch({ value: 'Permanent booth',key: 'period' })
} else {
dispatch({ value: '0',key: 'period' })
}
},[permanent])
它会在初始渲染时触发重新渲染,并且在渲染组件时我不会调用setPermanent
,我已经通过注释应用程序中的每个setPermanent
调用来检查了两者。而且我还尝试用登录到控制台的功能替换它。
//const [permanent,setPermanent] = useState(false)
const permanent = false
const setPermanent = () => {
console.log('I am called') //does not get called on initial render
}
我知道它会触发重新渲染,因为当我在其中注释第二个调度调用之一时,它不会触发重新渲染。
useEffect(() => {
if (permanent) {
dispatch({ value: 'Permanent booth',key: 'period' })
} else {
//dispatch({ value: '0',[permanent])
是否有原因,因为我似乎找不到解释这种行为的文档?
编辑--------------
const shopOptions = (() => {
const options = [
{ label: 'Choose a shop',value: '0' },]
Object.keys(stores).forEach(store => {
options[options.length] = { label: store,value: options.length }
})
return options
})()
const genderOptions = [
{ label: 'Choose a gender',{ label: 'Female',value: '1' },{ label: 'Male',value: '2' }
]
const periodOptions = [
{ label: 'Choose a period',{ label: '1 week',{ label: '2 weeks',value: '2' },{ label: '3 weeks',value: '3' },{ label: '4 weeks',value: '4' }
]
const initialState = {
shop: shopOptions[0],gender: genderOptions[0],period: periodOptions[0],}
function reducer(prevState,{ value,key }) {
const updatedElement = { ...prevState[key] }
updatedElement.value = value
return { ...prevState,[key]: updatedElement }
}
//form
const [state,dispatch] = useReducer(reducer,initialState)
解决方法
useEffect
钩子在首次渲染之后以及每次更新传递给依赖项数组的变量(在您的情况下为[permanent]
)之后运行。
由于您具有触发效果的布尔值,因此很难知道它是效果中的第一个渲染还是重新渲染。在您的情况下,我会考虑不在此处使用useEffect
,而是在更新状态时分派所需的内容。例如:
const [permanent,setPermanent] = useState(false)
const makePermanent = () => {
setPermanent(true)
dispatch({ value: 'Permanent booth',key: 'period' })
}
const makeTemporary = () => {
setPermanent(false)
dispatch({ value: '0',key: 'period' })
}
,
这是我的解决方案。只需一个布尔属性和排序钩即可完成工作。
const _isMounted = React.useRef(false)
const [filter,setFilter] = React.useState('')
React.useEffect(() => {
if (_isMounted.current) {
getData(filter) // Now it will not get called very first time
}
},[filter])
/* Order is important. [] or so called componentDidMount() will be the last */
React.useEffect(() => {
_isMounted.current = true
return () => {
_isMounted.current = false
}
},[])
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。