-
-
Notifications
You must be signed in to change notification settings - Fork 623
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
Avoid rerenders if atom value doesn't change #1158
Comments
I made a small change. I find it interesting that CounterComponent re-renders even though count is not changed because it's not increased. Just calling setCount with the same value causes a re-render.
|
This is something being asked several times. #1015 #1137 #1155
Now, this is a real problem. Thanks for sharing. My assumption is there are some heavy computations in a render function. Can you guess what they are? If so, wrapping with
For now, I don't have a solution, but maybe spend some time to see if there are any better solutions. |
Yeah, this is more counter-intuitive than derived atom cases. |
Okay, what's news to me is that React changes |
#1159 should fix the same value with non-derived atoms #1158 (comment). For derived atoms as originally reported, this is working as expected. The solution for heavy computation is Closing this but I would love to hear the feedbacks. |
@dai-shi Thank you for the clarification! I didn't now about the difference between the render and the commit phase. I was able to find the source of my performance issues with the React profiler and a Off topic: Thank you for your great work on this library. I really love using it! |
It could be interesting to add the information on the documentation regarding this issue. In recoil a re-render happens only if the derived value changed whereas in Jotai a re-render happens every time the source atom changed. For instance in the part "Composing atoms" export const textAtom = atom('hello')
export const textLenAtom = atom((get) => get(textAtom).length) Even if the atom length doesn't change (but the text does "hello" becomes "hi !!") it will cause a rerender function MyComponent () {
const length = useAtomValue(textLenAtom); // Wil rerender when textAtom change no matter the result of textLenAtom
return <div>Text length : {length}</div>
} |
This behavior is intentional but not super understandable. I think it's described in the core api doc. |
@dai-shi This is an old issue but I am wondering if there is any solution for the "do not re-render derived atoms when the value is same" problem. And I don't understand how It would be nice if there is a way to access that value that only re-renders if the value changes, e.g. via |
This behavior is changed in v2. It's one of the reasons we introduced v2. |
I tried with with the similar example, and cannot see derived atom renders when the value is changed ( after dai-shi's update).
and test code:
maybe the re-rendering is because of react version? I didn't test with react 16. |
this approach in the new version 2.2.0 is not working any more, is causing a infinite loop const state = useAtomValue(selectAtom(rootAtom, getValues)); |
Is |
I think this code itself create infinite loop since when you call selectAtom, it create a new atom triggering useAtomValue to rerender. |
I have memorized the selector , it was working before as per documentation says using a callback memorizing the resulting selector |
Can you identify which version causes the issue at first? |
it was working in the version 2.1.1, and I updated now to 2.2.0 and start doing the infinite loop. maybe something with the new implementation of async states it maybe is detecting an async function new over and over, I dint investigate any thing im just guessing |
That's sounds unexpected, because nothing around async behavior is changed since v2.1.1. Would you be able to create a minimal reproduction that works in v2.1.1 and fails in v2.2.0 with https://csb.jotai.org ? Once done, please open a new issue. |
I did, but seems to be working, the exact replication, I don't know... https://codesandbox.io/s/nervous-wood-fnhxyz?file=/src/App.tsx |
the thing is probably there is nothing in the store so is always the same, the resulting values. in my application there is updates and async updates that updates the atom and that's maybe the root of the problem |
it just happen in the mount, if the app was already mount and does that, everything works, maybe the cause is the use of use hook ?? not been supported in react-native --- edit --- I see you reexported the method, so it should work. I really don't know what happen but it was working before. and only happens in the first mount |
I got the issue, and yes is about the async new features or the better handling... the throw that return this : const state = useAtomValue(selectAtom(rootAtom, getValues)); is breaking the react flow in react native, I maybe need to wrap this in a suspense, but I wasn't specting this as the useAtomValue to be asynchronous and returning a throw promise, this is what is breaking everything. why it does not happen if I don't use the selectAtom ? |
I'm a bit confused, it is a new issue introduced in v2.2.0, or is it an issue in selectAtom that's there before that? Or, is it an issue even without selectAtom? Thanks for your investigation! |
I tried reproducing the issue in a sample repo with next.js and i'm not seeing any unecessary rerenders, heres a little demo Heres a sample repo of my demo but the issue seems to be resolved (if there was ever one) i thought also i had the same issue since i'm using heavily jotai with react query but all the rerenders seem to be because of a lack of useMemo and useCallback. Maybe i'm wrong but i think it's clear now. Thanks @dai-shi for all the hard work! 🙏 |
Currently a React Component that uses an readonly atom, gets always rerendered if one of the atoms dependencies changes. Even if the value of the atom is the same.
I created an example to demonstrate the issue:
https://codesandbox.io/s/jotai-rerender-demo-pgr5ep?file=/src/App.tsx
If you click the button,
ComponentA
is always rendered, even if its atom value never changes.This behaviour causes performance issues in one of my apps, which has a very big state (
stateAtom
) that comes from the server and is therefore saved in one atom, and heavily usesselectAtom
to split the big state into smaller atoms. Everytime thestateAtom
is updated, most of the App gets rerendered, even if the state change affects just one component.This sandbox demonstrates the same issue with
selectAtom
:https://codesandbox.io/s/jotai-rerender-demo-select-m3umz7
I expected that a component would only update if the value of the atom changes.
Is there a way to prevent this issue?
The text was updated successfully, but these errors were encountered: