- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设我有一个缓慢的组件,那么记住它是有意义的,例如
const SlowButton = ({onClick}) => {
// make some heat
const value = (function f(n) { return n < 2 ? Math.random() : f(n-1) + f(n-2)})(32)|0;
return <button onClick={() => onClick(value)}>{value}</button>
}
const MemoButton = React.memo(SlowButton);
如果我在组件中使用 MemoButton,例如:
const Counter = () => {
const [clicks, setClicks ] = useState(0);
const handleClick = () => {
setClicks(clicks + 1);
}
return <div>
<div>{clicks}</div>
<MemoButton onClick={handleClick} />
</div>
}
然后 MemoButton 每次仍然会重新渲染,因为 onClick
属性每次渲染都是一个新函数。解决这个问题非常简单:
const Counter2 = () => {
const [clicks, setClicks] = useState(0);
const handleClick = useCallback(() => {
setClicks(c => c + 1);
},[]);
return <div>
<div>{clicks}</div>
<MemoButton onClick={handleClick} />
</div>
}
上面的代码工作得很好,但是对于更复杂的组件,它就不太好用了:
const CounterGroup = () => {
const numButtons = 3;
const [message, setMessage] = useState('button X clicked');
const handleClick = (val, idx) => setMessage(`button ${idx} clicked: ${val}`);
return <div>
<div>{message}</div>
{Array(numButtons).fill(0).map((_, i) =>
<MemoButton key={i} onClick={(v) => handleClick(v,i)} />)
}
</div>
}
在上面的代码中,(v) => handleClick(i,v)
始终是一个新的函数引用。 有没有一种好的技术可以防止它改变每个渲染?
一种可能性是忽略对 'on...' 属性的更改,但这只会产生新问题:
const compareValuePropsOnly = (prev, next) => Object.entries(prev).every(
([k, v]) => k.substr(0, 2) === "on" || v === next[k]
);
const MemoOnlyValsButton = React.memo(SlowButton, compareValuePropsOnly);
这是一个codesandbox版本: https://codesandbox.io/s/memoization-function-reference-changes-9c1fy
最佳答案
一种解决方案是让您的 SlowButton
传递 i
值,而不是从循环中获取它,并记住 handleClick
const SlowButton = ({onClick, i}) => {
// make some heat
const value = (function f(n) { return n < 2 ? Math.random() : f(n-1) + f(n-2)})(32)|0;
return <button onClick={() => onClick(value, i)}>{value}</button>
}
const MemoButton = React.memo(SlowButton);
const CounterGroup = () => {
const numButtons = 3;
const [message, setMessage] = useState('button X clicked');
const handleClick = React.useCallback((val, idx) => setMessage(`button ${idx} clicked: ${val}`), []);
return <div>
<div>{message}</div>
{Array(numButtons).fill(0).map((_, i) =>
<MemoButton key={i} i={i} onClick={handleClick} />)
}
</div>
}
另一种方法是在 React.memo
中排除“onClick”属性(因为它是一个事件处理程序,所以它不应该影响组件的外观)。
const MemoButton = React.memo(SlowButton, (props1, props2) => {
// assume that SlowButton have some props that affect it's UI
// we don't compare onClick because it won't affect UI
return props1.someUIProps === props2.someUIProps;
})
或者您可以使用 useEventCallback
Hook 来记录您的函数。在这种情况下,您需要在 CounterGroup
和 MemoButton
const useEventCallback = (callback) => {
// store latest callback
const ref = useRef(callback);
useEffect(() => ref.current = callback);
// memoize the callback to maintain its identity
return useCallback((...args) => ref.current(...args), []);
}
const FastButton = ({onClick} => {
// FastButton will be re-rendered multiple times, but since memoOnClick have same identity
// on sub sequence re-renders, MemoButton should not be re-rendered
const memoOnClick = useEventCallback(onClick);
return <MemoButton onClick={memoOnClick} />
});
const CounterGroup = () => {
const numButtons = 3;
const [message, setMessage] = useState('button X clicked');
const handleClick = (val, idx) => setMessage(`button ${idx} clicked: ${val}`);
return <div>
<div>{message}</div>
{Array(numButtons).fill(0).map((_, i) =>
<FastButton key={i} onClick={(v) => handleClick(v,i)} />)
}
</div>
}
关于javascript - react 性能: What is a good strategy to maintain constant references for event handler props?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60251762/
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 可以用事实和引用来回答它. 3年前关闭。 Improve this
作为我不久前写的代码标准文档的一部分,我强制要求“您必须始终对循环和/或条件代码块使用大括号,即使(尤其是)它们只有一行。” 例子: // this is wrong if (foo) //b
我们正在创建一个大项目,该项目将持续存在并改进大约 10 年。 在我们的代码库中,已经有很多针对特定浏览器不兼容性的代码、针对浏览器中不同错误的解决方法、3rd 方工具和库等。代码本身通常运行良好,但
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 7年前关闭。 Improve t
感谢您花时间查看我的问题! 假设有一个 Web 服务(restful、SOAP、XML/JSON,无论你想要什么),并且它是一个关于小狗的服务。就本问题而言,小狗可以有两个成员变量。第一个是小狗的唯一
我的类经常有一些属性,而其他对象的属性依赖于这些属性。定义和访问它们的最佳方式是什么?一个最小的例子应该可以解释我的问题。 假设我有一个定义圆的类: class Circle: def __i
在一个应用程序中,我正在逐个读取无向图的顶点,只有当两个顶点都出现时,边才会变得明显。 解析后,我需要快速地逐一迭代图的连通分量。我选择什么算法来在解析时构建连接的组件? (在解析时,因为列出边相当昂
我目前正在将一个 API 从 C# 转换为具有网络组件的 Java。 C# 版本似乎在其类被使用期间保持输入和输出流以及套接字打开。 这是正确的吗? 请记住,应用程序根据用户输入发送命令和接收事件,为
在座的每一位可能对 Googlebot 的工作原理有一定了解的人都可能清楚地看到启动页面会损害网站的 SEO 性能。 但是,我碰巧正在处理一个相当不幸的案例,即必须为我的一个客户实现启动页面。你如何在
我正在尝试使用一些 iPhone Core Data 代码来调试一个非常邪恶的问题。 设置是这样的:我有一个线程来轮询Web服务并通过NSNotification将其结果发送到主线程(在userDic
我正在尝试通过开发类似 Web 应用程序的服务来更加熟悉 Haskell。 假设我正在开发一个网络服务器,并且我想在请求之间保持持久状态;例如,计数器。 Haskell 的做事方式是什么? 我遇到了这
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 9 年前。 Improv
所以我尝试为 List 创建一些基本的扩展方法。本质上我有一个 UniqueAdd 和 UniqueAddRange。它会在添加之前检查一个值是否存在,如果它已经在列表中,它就不会添加它。这是代码:
考虑一个具有可比较字段(与 equals 一致)和不可比较字段(我不知道它是否覆盖 Object#equals 的类)的类。 应比较类的实例,其中结果顺序应与相等一致,即 0 返回 iff 两个字段相
我试图将页脚设置在页面底部,并且我设法使用 CSS 属性“position:fixed”和“bottom:0”做到了这一点。但是,通过这样做,我的两个页脚 DIV 之间不再有空格。我一直在解决这个问题
目标:通过一个连接和多个 session 或一个持久 session 远程控制 ssh 服务器。 问题 1:我目前使用 sshj 通过 SSH 进行一些远程控制,它运行良好,但我似乎无法让它正确处理提
我有一个 Controller ,其中包含一些私有(private)只读接口(interface)属性,它需要这些属性才能通过调用服务来获取数据,然后用于填充模型等 private readonly
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 5 年前。 Improve
我 fork 了一个上游仓库,克隆了它,并创建了一个分支来处理一些事情 完成分支编码后,我创建了一个 merge 请求。但是在页面上有一个复选框“允许维护者编辑”? 这是什么意思?这是否意味着上游
我正在将 Kohana v3 用于 Web 项目,今天我发现自己在写这个: echo Html::anchor('user/view/'.$user->id, "See user's profile"
我是一名优秀的程序员,十分优秀!