question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Recoil state updates are out of sync with React component state

See original GitHub issue

Recoil version: 0.3.1 React version: 17.0.2

If a component has both Recoil state and React component state, and both are updated at once, a full render will occur (including effects and committing to the DOM) with the old Recoil state and the new React component state, before re-rendering with the new Recoil state.

This still occurs when:

  • unstable_batchedUpdates is used
  • React 18 alpha is used (even with ReactDOM.createRoot)

Example code

import { atom, useRecoilState } from "recoil";
import React, { useEffect, useState } from "react";

const indexAtom = atom({
  key: "index",
  default: 0
});

export const TestComponent = () => {
  const [stateIndex, setStateIndex] = useState(0);
  const [recoilIndex, setRecoilIndex] = useRecoilState(indexAtom);

  useEffect(() => {
    console.log("=== Effect from render ===");
    console.log("Local state: ", stateIndex);
    console.log("Recoil state: ", recoilIndex);
  });

  return (
    <button
      onClick={() => {
        setRecoilIndex(recoilIndex + 1);
        setStateIndex(stateIndex + 1);
      }}
    >
      Local state: {stateIndex} <br />
      Recoil state: {recoilIndex}
    </button>
  );
};

When clicking the button, you’ll see the following being output:

=== Effect from render === 
Local state:  
0
Recoil state:  
0
=== Effect from render === 
Local state:  
1
Recoil state:  
0
=== Effect from render === 
Local state:  
1
Recoil state:  
1

Notice how on the second effect, local state and recoil state are different, despite being set to the same value on the same call.

I would expect the second effect to never occur - if component state and Recoil state are set simultaneously, they should be updated atomically.

Codesandbox demo: https://codesandbox.io/s/sharp-https-3ydwz?file=/src/TestComponent.js

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:7
  • Comments:14 (5 by maintainers)

github_iconTop GitHub Comments

4reactions
theninthskycommented, Aug 24, 2021

Same as above, as we are heavily relying on this feature 😃 We might be misusing things, but I find it very convenient to use useState and useRecoilState interchangeably in conjunction with useEffect.

1reaction
timiscodingcommented, Aug 26, 2021

If you can’t wait for the fix, you could patch-package 0.4.0 by enabling the feature flag and install react@next and react-dom@next which includes the requisite useMutableSource hook. I get a warning about not using the newer ReactDOM.createRoot API so it’ll behave like React 17 which is fine by me as I’m not ready to opt into concurrent mode.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Recoil Sync Library
The recoil-sync NPM package provides an add-on library to help synchronize Recoil state with external systems. Simple asynchronous data queries can be ...
Read more >
Sync State Across Components with Recoil in React
This course will give you a clear understanding of how to start managing state with Recoil. Recoil is a state management library for...
Read more >
React / Recoil - when is setAtom new value available?
It's not related to Recoil but to React, the updated value is available on the next render as setState (which Recoil is built...
Read more >
Recoil: the Future of State Management for React? - Syncfusion
Atoms are both updatable and subscribable state units. As a result, all subscribed components are rerendered with the new value when an atom...
Read more >
recoil-sync - NPM Package Overview - Socket.dev
recoil -sync provides an add-on library to help synchronize Recoil state ... A child of RecoilRoot could sometimes have its state updated ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found