facebookexperimental / Recoil

Recoil is an experimental state management library for React apps. It provides several capabilities that are difficult to achieve with React alone, while being compatible with the newest features of React.
https://recoiljs.org/
MIT License
19.5k stars 1.18k forks source link

Nested RecoilRoot using initializeState has unexpected results #2299

Open mildfuzz opened 5 months ago

mildfuzz commented 5 months ago

Our app uses Recoil, but also consumes a library component that also use Recoil. They both use initializeState. The expectation is that we can initialise atoms related to the outer store in the outer RecoilRoot, and atoms related to the inner store in the inner RecoilRoot. I have contrived a reduced example of what we're trying to achieve:

function Comp() {
  const outer = useRecoilValue(outerState)
  const inner = useRecoilValue(innerState)
  return (
    <div>
      <pre>{JSON.stringify({outer, inner}, null, 4)}</pre>
    </div>
  )
}
function App() {
  return (
    <RecoilRoot
      key={'outer'}
      initializeState={({set}) => {
        console.log('outer')

        set(outerState, 'outer state')
      }}>
      <RecoilRoot
        key={'inner'}
        initializeState={({set}) => {
          console.log('inner')
          set(innerState, 'inner state')
        }}>
        <Comp />
      </RecoilRoot>
    </RecoilRoot>
  )
}

The expected output of the above is:

{
    "outer": "outer state,
    "inner": "inner state"
}

The actual result is:

{
    "outer": null,
    "inner": "inner state"
}