Let's say I have some state variable width
, and I know it will never change, but I need to run some putations on it based on a prop I receive. I don't want to do it in the body of the function, as it will run on every re-render. So:
const SOME_CONSTANT_NUMBER = 50;
const someFunc = ({multiplier: number}) => {
const [width, setWidth] = useState(SOME_CONSTANT_NUMBER * multiplier);
return (
<div>
{width}
</div>
);
}
Now I've also instantiated a function setWidth
that I will never use.
I could use a hook to run only on mount, but that's more code and not necessary.
const SOME_CONSTANT_NUMBER = 50;
const someFunc = ({multiplier: number}) => {
const [width, setWidth] = useState(0);
useHook(() => {
const updatedWidth = SOME_CONSTANT_NUMBER * multiplier;
setWidth(updatedWidth);
}, []);
return (
<div>
{width}
</div>
);
}
I think the worst approach would be below, as it will calculate it on every rerender:
const SOME_CONSTANT_NUMBER = 50;
const someFunc = ({multiplier: number}) => {
const width = SOME_CONSTANT_NUMBER * multiplier;
return (
<div>
{width}
</div>
);
}
*Note this example is simple, but assume there are much more props, and that the putation for this width
is putationally heavy.
Let's say I have some state variable width
, and I know it will never change, but I need to run some putations on it based on a prop I receive. I don't want to do it in the body of the function, as it will run on every re-render. So:
const SOME_CONSTANT_NUMBER = 50;
const someFunc = ({multiplier: number}) => {
const [width, setWidth] = useState(SOME_CONSTANT_NUMBER * multiplier);
return (
<div>
{width}
</div>
);
}
Now I've also instantiated a function setWidth
that I will never use.
I could use a hook to run only on mount, but that's more code and not necessary.
const SOME_CONSTANT_NUMBER = 50;
const someFunc = ({multiplier: number}) => {
const [width, setWidth] = useState(0);
useHook(() => {
const updatedWidth = SOME_CONSTANT_NUMBER * multiplier;
setWidth(updatedWidth);
}, []);
return (
<div>
{width}
</div>
);
}
I think the worst approach would be below, as it will calculate it on every rerender:
const SOME_CONSTANT_NUMBER = 50;
const someFunc = ({multiplier: number}) => {
const width = SOME_CONSTANT_NUMBER * multiplier;
return (
<div>
{width}
</div>
);
}
*Note this example is simple, but assume there are much more props, and that the putation for this width
is putationally heavy.
- If you need to run calculations with the new props, then you're going to have to recalculate, isn't that the point? – Colin Ricardo Commented May 24, 2019 at 19:10
- Sort of just how hooks work, unless you're looking to memoize and then there will still need to be checks for if the multiplier changed – WilliamNHarvey Commented May 24, 2019 at 19:11
3 Answers
Reset to default 6There is useMemo
for exactly that usecase.
const width = useMemo(() => SOME_CONSTANT_NUMBER * multiplier, [multiplier]);
Note that useMemo
itself es with a cost (it's another function) so you should use it only if you know that calculating the value is really costly meaning: causes lags (if not you should really check performance, and wether useMemo
increases it).
You don't really need to serailize it on the state, but let's follow your approach:
const MY_RATIO = 3
const SomeComponent = ({value}) =>{
const [state, setter] = useState(value * MY_RATIO)
useEffect(() =>{
setter(value * MY_RATIO)
}, [value, MY_RATIO])
}
Now you are only updating the state when your prop value
changes. But a better approach would be to use useMemo
const memoizedValue = useMemo(() => MY_RATIO * value, [MY_RATIO, value])
Seems like you should be using the useMemo hook https://reactjs/docs/hooks-reference.html#usememo
const width = useMemo(() => SOME_CONSTANT_NUMBER * multiplier , [multiplier])