了解useEffect()和useState()钩子的行为



所以我有一段代码不能按预期工作。当前焦点是使用useState((对父组件设置的,因此它是一个状态变量。但是,当父级中的currentFocus值发生更改时,此处的焦点变量本身不会更新。我本以为会重新渲染父组件,这反过来会重新渲染该组件,从而导致foucs值发生变化。

import React, { useRef, useEffect, useState } from 'react';
const CookieDetails = props => {
const {
name,
cost,
value,
numOwned,
onMouseClick,
cookieId,
currentFocus,
} = props;
let cookieInfoRef = useRef(null);
//My focus doesnt change even if I change currentFocus in parent component
const [focus, setFocus] = useState(currentFocus);
useEffect(() => {
console.log('currentFocus', currentFocus);
console.log('focus', focus);
console.log('cookieID', cookieId); 
if (cookieInfoRef.current && cookieId === focus) {
console.log('current', cookieInfoRef.current);
cookieInfoRef.current.focus();
}
}, [focus]);
return (
<React.Fragment>
<button
onClick={onMouseClick}
ref={cookieId === focus ? cookieInfoRef : null}
>
<h3>{name}</h3>
<p>Cost:{cost}</p>
<p>Value:{value}</p>
<p>Owned:{numOwned}</p>
</button>
</React.Fragment>
);
};
export default CookieDetails;

现在我可以通过以下操作来解决这个问题,

import React, { useRef, useEffect, useState } from 'react';
const CookieDetails = props => {
const {
name,
cost,
value,
numOwned,
onMouseClick,
cookieId,
currentFocus,
} = props;
let cookieInfoRef = useRef(null);
useEffect(() => {
console.log('currentFocus', currentFocus);
console.log('cookieID', cookieId);        
if (cookieInfoRef.current && cookieId === currentFocus) {
console.log('current', cookieInfoRef.current);
cookieInfoRef.current.focus();
}
});
return (
<React.Fragment>
<button
onClick={onMouseClick}
ref={cookieId === currentFocus ? cookieInfoRef : null}
>
<h3>{name}</h3>
<p>Cost:{cost}</p>
<p>Value:{value}</p>
<p>Owned:{numOwned}</p>
</button>
</React.Fragment>
);
};
export default CookieDetails;

但我只想在focus/currentFocus更新时运行useEffect挂钩,而不是在每次渲染之后。那么为什么会发生这种情况呢?我在这里缺少什么来理解。

我之前也注意到,如果你这样做,handleStuff函数总是使用初始值100(所以它总是100+10(,而不是每次按键都增加10。我可以通过删除useEffect中作为第二个参数的空[]来解决这个问题。然而,我希望handleStuff仍然使用最新的值更新,因为eventListner已经在初始渲染时添加,在第二次关键帧按下时,它应该添加10到110,而不是100,但它一直使用初始状态值100。为什么你必须清除旧的听众,每次都添加新的听众才能奏效?

[value, setValue] = useState(100)
handleStuff = (event) => {
setValue(value+10)
}
useEffect(() => {
window.addEventListener('keydown', handleStuff)
return () => {
window.removeEventListener('keydown', handleStuff)
}
},[]);

我对解决方案并不感兴趣,我真正感兴趣的是理解useEffect((和useState((钩子在这种情况下是如何工作的。

嘿,useEffect钩子可能有点令人困惑。但我们的想法是

useEffect(() => {
// Called in an infinite loop (most cases you won't need this)
})
useEffect(() => {
// Called on first render
}, [])
useEffect(() => {
// Called when x y & z updates
}, [x, y, z])

问题是您没有在代码中侦听currentFocus更新。

useEffect(() => {
// Called when focus updates
}, [focus]);
useEffect(() => {
// Called when props.currentFocus & focus updates
}, [props.currentFocus, focus]);

现在来解释你的困惑:

// My focus doesnt change even if I change currentFocus in parent component
const [focus, setFocus] = useState(currentFocus);

当您在这里传递currentFocus时,currentFocus值被传递到焦点useState的唯一时间是在第一次渲染时。因此,你需要倾听currentFocus的更新,然后设置新的焦点,它应该按照你想要的方式工作!

// Focus set to props.currentFocus on first render
const [focus, setFocus] = useState(currentFocus);
useEffect(() => {
// Update focus
setFocus(props.currentFocus)
}, [props.currentFocus])
useEffect(() => {
// currentFocus will be the same as focus now
console.log('currentFocus', currentFocus);
console.log('focus', focus);
console.log('cookieID', cookieId); 
if (cookieInfoRef.current && cookieId === focus) {
console.log('current', cookieInfoRef.current);
cookieInfoRef.current.focus();
}
}, [focus]);

希望能有所帮助!

相关内容

  • 没有找到相关文章

最新更新