I'm trying to create a custom hook useFocus based on useContext to set the focus only on the component i select. Its working but other components are rendering even i used useCallback for the function returned by my useFocus custom hook.
i would like to rerender only the components with changing focus.
I know rerender can be minor issue if the code is fast but i can't understand why it's re-render. Could you give me some explanation or a fix.
Expected result :
When clicking on 'set focus' button, I expect to get :
1 render for A/B/D
2 renders for C/E
Thanks.
Here my code :
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>
);
}