reactjs - 将内联 reducer 函数传递给 React.useReducer
问题描述
让我们以内联减速器为例:
const App = () => {
const [state, dispatch] = React.useReducer(s => {
console.log("reducer invoked with state", s)
return s + 1
}, 0);
return (
<div>
<p>{state}</p>
<button onClick={dispatch}>Increment</button>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js" integrity="sha256-32Gmw5rBDXyMjg/73FgpukoTZdMrxuYW7tj8adbN8z4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js" integrity="sha256-bjQ42ac3EN0GqK40pC9gGi/YixvKyZ24qMP/9HiGW7w=" crossorigin="anonymous"></script>
<div id="root"></div>
在第一次单击时,App
会呈现两次,随后的单击只会导致一次重新呈现。
我想了解上述行为useReducer
。阅读此答案后,有些事情我仍然不清楚。
- 为什么只有第一次触发双重渲染
useReducer
? - 1.) 是否还有其他情况,这也会导致内联减速器的双重渲染?
- 什么时候不推荐这种内联减速器模式(性能等)?还是没有缺陷?
解决方案
通过将 reducer 函数放在组件中,您可以在每次组件呈现时创建一个新函数。它可能有相同的文本,但 react 无法分辨,所以它被迫运行新旧函数并比较它们的结果。
在下面的代码片段中,我让 reducer 函数注销了正在运行的函数实例,您会看到前两个双重调用是两个不同的函数。我不确定为什么以后不需要也这样做
let count = 0;
const App = () => {
count++;
const [state, dispatch] = React.useReducer(s => {
console.log(`reducer #${count} invoked with state`, s)
return s + 1
}, 0);
return (
<div>
<p>{state}</p>
<button onClick={dispatch}>Increment</button>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js" integrity="sha256-32Gmw5rBDXyMjg/73FgpukoTZdMrxuYW7tj8adbN8z4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js" integrity="sha256-bjQ42ac3EN0GqK40pC9gGi/YixvKyZ24qMP/9HiGW7w=" crossorigin="anonymous"></script>
<div id="root"></div>
所以是的,使用内联减速器可以稍微降低性能。因此,如果您不需要内联它,那么您应该将它移到组件之外。
如果您确实需要内联它(例如,因为您需要引用组件内的其他变量),在大多数情况下这可能没什么大不了的。如果是,那么您可以使用Callback 来记忆它,并且只在需要时更改它。
const Example = () => {
const [size, setSize] = useState(1);
const reduction = useCallback((s) => {
console.log(`reducer called; something = ${something}`);
return s + size;
}, [something]l
const [state, dispatch] = useReducer(reduction, 0);
推荐阅读
- dataframe - 热图无法正确显示数据
- xml - XML 找不到似乎已经声明的元素的声明
- arrays - Turbo 汇编器中的字符串数组
- recaptcha - Google ReCaptcha v2 HIPAA 是否兼容?
- python - 卸载和安装 python 和 pycharm 后运行简单的 kivy 程序时出错 error:raise Exception('Invalid instance in App.root')
- node.js - Docker节点js容器不会运行
- java - 为什么集合中的 LinkedHashMap 没有像 HashMap 和 TreeMap 这样的 put 方法?
- c++ - c++ 变量声明中的两个“const”
- python - 即使在 pip install playsound 之后,我在导入 playsound 模块时也遇到错误
- python-3.x - 由于文件路径损坏,Libewf 安装无法正常工作?