如何使用自定义钩子和 useContext 仅渲染相关组件
Posted
技术标签:
【中文标题】如何使用自定义钩子和 useContext 仅渲染相关组件【英文标题】:How to render only the concerned component with a custom hook and useContext 【发布时间】:2021-09-12 08:04:37 【问题描述】:我正在尝试基于 useContext 创建一个自定义钩子 useFocus,以便仅将焦点设置在我选择的组件上。 即使我将 useCallback 用于我的 useFocus 自定义钩子返回的函数,它的工作但其他组件正在呈现。
我想只重新渲染焦点发生变化的组件。
我知道如果代码很快,重新渲染可能是小问题,但我不明白为什么要重新渲染。 你能给我一些解释或解决办法吗?
预期结果:
点击“设置焦点”按钮时,我希望得到:
1 个 A/B/D 渲染
2 个 C/E 渲染
谢谢。
这是我的代码:
import React, createContext, useCallback, useContext, useState from "react";
import "./styles.css";
const StepContext = createContext();
//This is just to display number or render for each Items
function useRenderCounter()
const ref = React.useRef();
React.useEffect(() =>
ref.current.textContent = Number(ref.current.textContent || "0") + 1;
);
return (
<span
style=
backgroundColor: "#ccc",
borderRadius: 4,
padding: "2px 4px",
fontSize: "0.8rem",
margin: "0 6px",
display: "inline-block"
ref=ref
/>
);
const useFocus = (property) =>
const context = useContext(StepContext);
const bool = context === property;
//console.log("bool", bool, context, property);
//return bool
return useCallback(() => bool, [bool]);
;
const Item = React.memo(( property ) =>
const rendercounter = useRenderCounter();
const isFocus = useFocus(property);
//Here I expect to got re-render only for property which the focus changed
const focus = isFocus();
console.log(property, "render", focus);
const style = focus ? borderStyle: "solid", borderColor: "red" : ;
return (
<div style= display: "flex", margin: "4px" >
rendercounter
<div style=style>property</div>
</div>
);
);
export default function App()
const [focusOn, setFocusOn] = useState("E");
const handleClick = () => setFocusOn("C");
return (
<StepContext.Provider value=focusOn>
<div style= display: "flex", flexDirection: "column" >
<Item key=1 property="A" />
<Item key=2 property="B" />
<Item key=3 property="C" />
<Item key=4 property="D" />
<Item key=5 property="E" />
<button onClick=handleClick>set focus</button>
</div>
</StepContext.Provider>
);
Here the sandbox
【问题讨论】:
我删除了我的答案,因为我注意到如果它不重新渲染,样式将始终为红色边框,因为焦点发生变化并重新评估,所以我不确定我的答案是否会无论如何申请。目的是什么? This thread might be helpful 【参考方案1】:当 Provider 获得新值时,无法避免重新渲染。来自official docs on Context API:
只要 Provider 的 value prop 发生变化,所有作为 Provider 后代的消费者都会重新渲染。从 Provider 到其后代消费者(包括 .contextType 和 useContext)的传播不受 shouldComponentUpdate 方法的约束,因此即使祖先组件跳过更新,消费者也会更新。
【讨论】:
以上是关于如何使用自定义钩子和 useContext 仅渲染相关组件的主要内容,如果未能解决你的问题,请参考以下文章
在使用数据库数据更新上下文后,React 'useContext' 钩子不会重新渲染
使用 React 钩子 useContext 避免不必要的重新渲染
使用新的 React 钩子 useContext 的正确方法是啥?
如何将 React 钩子(useContext、useEffect)与 Apollo 反应钩子(useQuery)结合起来