New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bug: useMemo hook executes twice #24935
Comments
Why does it matter if it executes once or twice? Since any function inside useMemo should be pure, it should make no difference. Is this a performance concern, or does it change the behavior in some observable way (when you follow the rules)? |
@TheDevCactus I understand that there is a warning, but this is not an error. The example is just a simulation how to make the bug to appear. I hope it will help somehow. React doesn't show any warning or something in my project, so it was hard enough to spot the issue. |
@gaearon Yeah, it causes unpleasant problems with performance, because the returned value from |
just to add that I'm also having this issue now with the same version and found this thread, this is a problem because I use the hook to control debounce to an expensive REST api, and if it is executed twice (which it is now) then that's a problem because the target API is used twice than it should which can cause race conditions transactional issues and at the production cloud level that amounts to twice the consumption on cloud function/serverless apis which eats up half of my paid for allocation. |
The docs explicitly says:
You can try achieve semantic guarantee using https://reactjs.org/docs/hooks-faq.html#how-do-i-implement-getderivedstatefromprops. |
Same here, I'm using a dependency injection framework factory method inside useMemo to create one instance of a model inside my component, using react 18 triggers useMemo few times for no reason. |
Please check this https://reactjs.org/docs/hooks-faq.html#how-to-create-expensive-objects-lazily. You can manually save this instance to ref on very first render (or even lazily). |
This is gold! thank you! |
@dmytro-vasylenko the message says "warning" but the log level is error and we consider this an error. It's hard to say exactly what's going on here because it's violating a few patterns, so it's not unexpected that we end up needed to re-memoize the value. Are you able to create a repro that's closer to your use case that doesn't error or depend on calling setState inside useMemo to reproduce? |
I call |
Seems like useEffect is what you need. |
This is a real https://codesandbox.io/s/compassionate-swartz-wd3j94?file=/src/App.js Or is this normal in strict mode? |
Yes, I see this is normal https://reactjs.org/docs/strict-mode.html |
I am facing exactly same issue! |
This is exactly how I ran into this!
FWIW, function useObjectUrl(blob) {
const ref = useRef();
const dispose = () => ref.current && URL.removeObjectURL(ref.current.url);
useEffect(() => dispose, []);
if (ref.current && blob === ref.current.blob) {
return ref.current.url;
}
dispose();
const url = URL.createObjectURL(blob);
ref.current = { blob, url };
return url;
} |
Recently we faced the issue with Investigation led us to the moment where React picks the right hook implementation - react/packages/react-reconciler/src/ReactFiberHooks.js Lines 543 to 559 in c5b9375
In our case it was picking Meaning:
So the only "stable" way to perform operation once is to perform it in |
This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment! |
useRef content clears too :( |
With Suspense, it's expected that some components re-execute when the suspense resolves (all the components up to the component that suspended). Generally, components need to be designed to be able to re-run or run without mounting, for example when something else rendered before the suspense was resolved. |
I'm using
useMemo
hook with an empty dependency array in a component withlazy
+Suspense
, so I expect the function insideuseMemo
will be called once, but sometimes the function is called twice.No
StrictMode
, no rerenders.React version:
18.2.0
I can't reproduce it with version
17.0.2
Steps To Reproduce
Please, take a look at the simplified example. I could reproduce it on a regular basis after I've added
setState
call insideuseMemo
. As the issue is hard to reproduce, there is a script that reloads the page until the bug appears.Link to code example: https://codesandbox.io/s/smoosh-forest-g6ft5o
Pay attention, that function in
useEffect
was called once, which is expected behavior, butuseMemo
was called twice.In the real project, there is no
setState
call insideuseMemo
and no warnings, but anyway I meet the issue every 10-20 page reloads.If I delete
lazy
it works as expected. If I dropLongComponent
it works as expected.The current behavior
The function passed to
useMemo
is executed twice despite the empty dependency array, and the component wasn't rerendered.The expected behavior
The function passed to
useMemo
is executed only once.The text was updated successfully, but these errors were encountered: