javascript - 了解 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;
但我只想在更新焦点/当前焦点时运行 useEffect 挂钩,而不是在每次渲染后运行。那么为什么会这样呢?我在这里想了解什么。
另外我之前注意到,如果你做了这样的事情,handleStuff 函数总是使用初始值 100(所以它总是 100 + 10),而不是每次按下一个键时递增 10。我可以通过删除空的 [] 作为 useEffect 中的第二个参数来解决这个问题。但是,我希望 handleStuff 仍然使用最新值更新,因为 eventListner 已经在初始渲染时添加,并且在第二次 keydown 时它应该将 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 every render
})
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]);
希望有帮助!
推荐阅读
- ruby - 我应该如何解决这个错误?我对红宝石变量有疑问
- python - 从文本 Python 创建一个数组
- unicode - 为什么这个 AutoHotKey 脚本偶尔不执行前 250 行?
- flutter - 退出应用时 Flutter 保存应用状态(登录首页后应用从登录页面启动)
- url - 是否可以参数化网络 [URL] 查询?
- html - 带链接的引导卡中同样高
- swift - 检查两个位置之间的距离(以 KM 为单位)
- python - 将熊猫系列标签拆分为python中新数据框的索引和列?
- java - java - 如何在Java Spring Boot中将一个对象映射到另一个对象
- json - 如何在父级别要求中引用子属性