I need to pass some props to a third-party drawing library, but I need to pass only the initial value of the prop. I've made a wrapper component which captures the initial props in state, and then passes them to the third-party component.
This works, but since setZoom and setCenter aren't used, it feels like an anti-pattern:
function Wrapper({ center, zoom }) {
const [initialZoom, setInitialZoom] = useState(zoom);
const [initialCenter, setInitialCenter] = useState(center);
return <ThirdParty zoom={initialZoom} center={initialCenter} />
}
I tried useMemo but eslint also warned about missing dependencies:
React Hook useMemo has a missing dependency: 'zoom'. Either include it or remove the dependency array.eslintreact-hooks/exhaustive-deps
function Wrapper({ center, zoom }) {
const initialZoom = useMemo(() => zoom, []); // eslint-disable-line react-hooks/exhaustive-deps
const initialCenter = useMemo(() => center, []); // eslint-disable-line react-hooks/exhaustive-deps
return <ThirdParty zoom={initialZoom} center={initialCenter} />
}
Is there an idiomatic way to do this? Or is it so non-standard that just ignoring the eslint warnings on the useMemo example is the best option?
This works, but since setZoom and setCenter aren't used, it feels like an anti-pattern:
function Wrapper({ center, zoom }) { const [initialZoom, setInitialZoom] = useState(zoom); const [initialCenter, setInitialCenter] = useState(center); return <ThirdParty zoom={initialZoom} center={initialCenter} /> }
This isn't so much anti-pattern as much as it is just unused declarations. You don't need to destructure the state updater function. Just set the initial value and don't ever update it.
function Wrapper({ center, zoom }) {
const [initial] = useState({ center, zoom });
return <ThirdParty zoom={initial.zoom} center={initial.center} />
}
I tried useMemo but eslint also warned about missing dependencies:
React Hook useMemo has a missing dependency: 'zoom'. Either include it or remove the dependency array.eslintreact-hooks/exhaustive-deps
function Wrapper({ center, zoom }) { const initialZoom = useMemo(() => zoom, []); // eslint-disable-line react-hooks/exhaustive-deps const initialCenter = useMemo(() => center, []); // eslint-disable-line react-hooks/exhaustive-deps return <ThirdParty zoom={initialZoom} center={initialCenter} /> }
This is also a valid use case, using an empty dependency array to run the hook once on component mount, but as you see, the react hook linting rules will complain about a possible missing dependency.
Other alternatives include:
Using a React ref to hold the initial values:
function Wrapper({ center, zoom }) {
const initialRef = useRef({ center, zoom });
return <ThirdParty zoom={initialRef.zoom} center={initialRef.center} />
}
Instead of a wrapper component you may want a Higher Order Component to just memoize the initial props value.
Example:
const withMemoizedInitialProps = Component => props => {
const initialPropsRef = useRef(props);
return <Component {...initialPropsRef.current} />
};
...
const DecoratedThirdParty = withMemoizedInitialProps(ThirdParty);
...
<DecoratedThirdParty zoom={zoom} center={center} />
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With