简体   繁体   English

无法从 Function 访问 React Reducer 值

[英]Can't Access React Reducer Value from Function

In the code below, a keypress event detector is implemented through useEffect which attempts to update index through the useReducer function.在下面的代码中,按键事件检测器是通过useEffect实现的,它尝试通过useReducer function 更新index However, the console.log output doesn't seem to show that the update works even though the button component's value updates.但是,即使button组件的值更新, console.log output 似乎也没有显示更新有效。

On the other hand, when the button is clicked, the index variable seems to update as indicated by the console.log and the content of the button also updates as expected.另一方面,当单击按钮时, index变量似乎会按照console.log的指示进行更新,并且button的内容也会按预期更新。

Why is there such a disparity and - if I needed to access the updated index variable after a keypress, how could I go about doing it?为什么会有这样的差异 - 如果我需要在按键后访问更新的index变量,我怎么能 go 这样做呢?

The code is below:代码如下:

 const { useEffect, useReducer } = React; const indexReducer = (state, action) => { if (action === "decrease") { return state-1 } else if (action === "increase") { return state+1 } else if (action === "reset") { return 0 } } function App() { const [counter, setCounter] = useReducer(indexReducer, 0) const incrementCounter = () => { console.log(counter) setCounter("increase") } useEffect(() => { document.addEventListener("keydown", incrementCounter, false); return () => { document.removeEventListener("keydown", incrementCounter, false); }; }, []); return ( <div className="App"> <button onClick={incrementCounter}>{"COUNT: " + counter}</button> </div> ); } ReactDOM.render(<App />, document.body);
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>

incrementCounter is redefined on every render, and has a closure around the value of counter at the time it is defined. incrementCounter在每次渲染时都会重新定义,并且在定义时在counter的值周围有一个闭包。 In the keydown handler's case, this is 0 (since your effect only runs once).keydown处理程序的情况下,这是0 (因为您的效果只运行一次)。 Notice that the the onClick version is also always n-1 behind the button text.请注意, onClick版本也始终在button文本后面n-1

You can move your logging into your reducer:您可以将日志记录移动到减速器中:

 const { useEffect, useReducer } = React; const indexReducer = (state, action) => { if (action === "decrease") { return state-1 } else if (action === "increase") { console.log(state+1) return state+1 } else if (action === "reset") { return 0 } } function App() { const [counter, setCounter] = useReducer(indexReducer, 0) const incrementCounter = () => { setCounter("increase") } useEffect(() => { document.addEventListener("keydown", incrementCounter, false); return () => { document.removeEventListener("keydown", incrementCounter, false); }; }, []); return ( <div className="App"> <button onClick={incrementCounter}>{"COUNT: " + counter}</button> </div> ); } ReactDOM.render(<App />, document.body);
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>

Or use a functional setState :或使用功能setState

 const { useEffect, useState } = React; function App() { const [counter, setCounter] = useState(0) const incrementCounter = () => { setCounter(counter => { console.log(counter + 1) return counter + 1 }) } useEffect(() => { document.addEventListener("keydown", incrementCounter, false); return () => { document.removeEventListener("keydown", incrementCounter, false); }; }, []); return ( <div className="App"> <button onClick={incrementCounter}>{"COUNT: " + counter}</button> </div> ); } ReactDOM.render(<App />, document.body);
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM