无法从函数访问 React Reducer 值
Can't Access React Reducer Value from Function
在下面的代码中,按键事件检测器是通过 useEffect
实现的,它尝试通过 useReducer
函数更新 index
。但是,即使 button
组件的值更新,console.log
输出似乎也没有显示更新有效。
另一方面,单击按钮时,index
变量似乎按照 console.log
的指示更新,button
的内容也按预期更新。
为什么会有这样的差异 - 如果我需要在按键后访问更新的 index
变量,我该怎么做呢?
代码如下:
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
在每个渲染器上都被重新定义,并且在定义时围绕 counter
的值有一个闭包。在 keydown
处理程序的情况下,这是 0
(因为您的效果只运行一次)。请注意,onClick
版本也始终 n-1
在 button
文本之后。
您可以将日志移至您的减速器中:
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>
或者使用函数 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>
在下面的代码中,按键事件检测器是通过 useEffect
实现的,它尝试通过 useReducer
函数更新 index
。但是,即使 button
组件的值更新,console.log
输出似乎也没有显示更新有效。
另一方面,单击按钮时,index
变量似乎按照 console.log
的指示更新,button
的内容也按预期更新。
为什么会有这样的差异 - 如果我需要在按键后访问更新的 index
变量,我该怎么做呢?
代码如下:
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
在每个渲染器上都被重新定义,并且在定义时围绕 counter
的值有一个闭包。在 keydown
处理程序的情况下,这是 0
(因为您的效果只运行一次)。请注意,onClick
版本也始终 n-1
在 button
文本之后。
您可以将日志移至您的减速器中:
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>
或者使用函数 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>