polemius / recoil-persist

Package for recoil state manager to persist and rehydrate store

Home Page:https://polemius.dev/recoil-persist/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

recoil-persist not working as expected with useSetRecoilState in the useEffect hook

sarobolket opened this issue · comments

I want to update an atom with the query string in the URL. With useSetRecoilState I can set the atom but recoil-persist doesn't save in localStorage. I can see that the onSet callback in the effects of the atom is not triggered.

See this example:

import { atom } from 'recoil';
import { recoilPersist } from 'recoil-persist';

const { persistAtom } = recoilPersist();

export const atomState = atom({
  key: 'example',
  default: null,
  effects: [persistAtom],
});

import React from 'react';
import { Navigate } from 'react-router-dom';
import { useRecoilValue } from 'recoil';
import { atomState } from 'state';
import { useSaveQueryString } from 'hooks/useSaveQueryString';

function MobileRoute() {
  useSaveQueryString ();

  const state = useRecoilValue(atomState );

  if (state ) {
    return <Navigate to="/something" />;
  }

  return <div>Loading...</div>;
}

export default MobileRoute;
function useSaveQueryString () {
  const [search] = useSearchParams();
  const setAtom = useSetRecoilState(atomState);

useEffect(() => {
const searchAsObject = Object.fromEntries(new URLSearchParams(search));

  if (searchAsObject.id) {
    setAtom (searchAsObject.id);
  }
}, [search, setAuth])
}

How can I solve it? Some example with recoil-sync??

I had the same problem, and it turned out that it was the combination of React 18 and strict mode.
Inside an internal Recoil component called RecoilRoot_INTERNAL there is an useEffect() that initializes and cleans up the internal state store When Recoil runs in strict mode that effect is called multiple times and during all this reinitialization all effect subscriptions generated when calling onSet are removed.
So the workaround was to bail out of strict mode.