gpt4 book ai didi

reactjs - 为什么 useState 不使用 keydown 处理程序更新状态?

转载 作者:行者123 更新时间:2023-12-05 05:42:16 25 4
gpt4 key购买 nike

我正在尝试创建一个简单的 React 图像 slider ,其中向右/向左箭头键在图像中滑动。

问题

当我按一次向右箭头时,它按预期工作。 id 从 0 更新为 1,并重新渲染新图像。

当我第二次按向右箭头时,我看到(通过 console.log)它注册了击键,但没有通过 setstartId 更新状态。

为什么?

此外,我在组件函数本身中打印 new StartId: 0。我看到当您第一次渲染页面时,它打印了 4 次。为什么?是:1 个用于初始加载,2 个用于两个 useEffects,最后一个用于 promise 解决时?

代码

这是我的沙箱: https://codesandbox.io/s/react-image-carousel-yv7njm?file=/src/App.js

export default function App(props) {
const [pokemonUrls, setPokemonUrls] = useState([]);
const [startId, setStartId] = useState(0);
const [endId, setEndId] = useState(0);

console.log(`new startId: ${startId}`)

const handleKeyStroke = (e) => {
switch (e.keyCode) {
// GO LEFT
case 37:
break;
// GO RIGHT
case 39:
console.log("RIGHT", startId);
setStartId(startId + 1);
break;
default:
break;
}
};

useEffect(() => {
async function fetchPokemonById(id) {
const response = await fetch(`${POKE_API_URL}/${id}`);
const result = await response.json();
return result.sprites.front_shiny;
}

async function fetchNpokemon(n) {
let pokemon = [];

for (let i = 0; i < n; i++) {
const pokemonUrl = await fetchPokemonById(i + 1);
pokemon.push(pokemonUrl);
}
setPokemonUrls(pokemon);
}

fetchNpokemon(5);
}, []);

useEffect(() => {
window.addEventListener("keydown", handleKeyStroke);

return () => {
window.removeEventListener("keydown", handleKeyStroke);
};
}, []);

return (
<div className="App">
<Carousel pokemonUrls={pokemonUrls} startId={startId} />
<div id="carousel" onKeyDown={handleKeyStroke}>
<img alt="pokemon" src={pokemonUrls[startId]} />
</div>
</div>
);
}

最佳答案

handleKeyStroke() 调用 setStartId(prev=>prev+1)

更新了handleKeyStroke()

 const handleKeyStroke = (e) => {
switch (e.keyCode) {
// GO LEFT
case 37:
break;
// GO RIGHT
case 39:
console.log("RIGHT", startId);
setStartId(prev=>prev + 1);
break;
default:
break;
}
};

解释

在上面的代码中,您在 useEffect 中添加了 window.addEventListener,依赖数组为空。在 handleKeyStroke() 中,您以这种方式设置状态 setStartId(startId + 1);

由于 useEffect,当 handleKeyStroke() 被初始化时,它被初始化为挂载时可用的值。它不会访问更新后的状态。

因此,例如,当您调用 setStartId(startId + 1); 时,handleKeyStroke() 的值为 startId=0 并向其加 1。但是下次调用 setStartId(startId + 1); 时,handleKeyStroke 中的 startId 值仍然为 0。但是当我们使用回调语法时,它可以访问以前的状态。

关于reactjs - 为什么 useState 不使用 keydown 处理程序更新状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72080086/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com