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.61k stars 1.18k forks source link

Bug: DefaultValue returned from selector get instead of actual default #2152

Open ayroblu opened 1 year ago

ayroblu commented 1 year ago

I have the following code:

import { get, set } from "idb-keyval";
import type { AtomEffect } from "recoil";
import { DefaultValue, atom, selector } from "recoil";

export const syncIdbEffect =
  <T>(dbKey: string): AtomEffect<T> =>
  ({ onSet, setSelf }) => {
    setSelf(
      get(dbKey).then((savedVal: T | null) =>
        savedVal !== null || savedVal !== undefined ? savedVal : new DefaultValue(),
      ),
    );
    onSet((newVal, oldVal) => {
      if (newVal === oldVal) return;

      set(dbKey, newVal);
    });
  };

const tokenState = atom<string | undefined>({
  key: "tokenState",
  default: undefined,
  effects: [syncIdbEffect("token")],
});
export const isAuthedState = selector<boolean>({
  key: "isAuthedState",
  get: ({ get }) => {
    const refreshToken = get(tokenState);
    // MARK: At this stage refresh is of type "DefaultValue {}". TypeScript thinks that only string | undefined is the type
    return !!refreshToken;
  },
});

It's failing because the DefaultValue object is being returned from the get, where I'd expect the default to be undefined (see the MARK comment)

I'm using Recoil v0.7.6

xotahal commented 1 year ago

I believe this is a duplicity of https://github.com/facebookexperimental/Recoil/issues/2151

xotahal commented 1 year ago

This helped me - https://github.com/facebookexperimental/Recoil/issues/2151#issuecomment-1491111260

mluiten commented 8 months ago

I believe I'm experiencing this as well -- returning DefaultValue from a async (): Promise<T | DefaultValue> directly into setSelf will make it return DefaultValue, instead of the (explicitly set) default of undefined.

Seeing how this project no longer seems to be maintained, I'm starting the migration to jotai :(