LoginSignup
1
0

Recoilのatomをデフォルト値にリセットしてもAPIが送信されない

Last updated at Posted at 2023-08-11

はじめに

RecoilのatomをパラメーターにしてselectorでAPIを送信してました。
useResetRecoilStateでリセットしてatomの値を更新してもselectorがAPIを送信しないのが今回の問題です。
今回は 「ボタンを押すとデフォルト値に戻してAPIを送信する」 という動作を前提にしています

サンプルコード

// defaultFuncには何かしらのデフォルト値が設定されます
export const atomValue = atom({
  key: "atomValue",
  default: defaultFunc,
})

// atomをパラメーターにとり何かしらのAPIを送信する。
export const apiSelector = selector({
  key: "apiSelector",
  get: async ({ get }) => {
    const atomParam = get(atomValue)
    const respnse = await getApi(atomParam)
    return respnse
  }
})

export const sample = () => {
 const resetAtomValue = useResetRecoilState(atomValue)
  return (
     <Button
      onClick={resetAtomValue}
     >
     リセット
   </Button>
 }
)

色々と試してみた

  • ボタンを押した時に useResetRecoilStateを使用するのではなく、直接デフォルト値を設定する

  • ログを仕込んでatomボタンがが更新されているか確認する

  • useEffectを使用していたので、useEffectの副作用を疑って、できるだけレンダリングしないようにuseEffectを解体

  • reset関数を使用してリセットを行っているが、reset関数内の更新でatomが競合している可能性があるため、useRecoilCallBackを使用してみる

その後、selectorにログを仕込んで確認したところ、atomが更新されているのにも関わらずにselectorが実行されていないということがわかりました。
通常、selector内でgetしているatomが変更されるとAPIが送信されるはずです。
selector内ではしっかりとgetしています。const atomParam = get(atomValue)

解決策

RequestseIDをselector内のsetに用意して、リセットボタンを押下するたびにset内の処理も実行されるように変更しました。
そうすることで、強制的に更新させてAPIを送信するように修正しました。
処理の流れは以下になります
・リセットボタンを押下する
resetAtomValue()でatomがデフォルトの値にリセットされる
apiSelector()でsetが更新されてAPIが送信される

// RequestseIDを管理するatomを作成
export const apiSelectorRequestId = atom<number>({
  key: "apiSelectorRequestId",
  default: 0,
})

export const apiSelector = selector({
  key: "apiSelector",
  get: async ({ get }) => {
    const atomParam = get(atomValue)
    const respnse = await getApi(atomParam)
    return respnse
  },

// setを使用してatomを強制的に更新させる
  set: ({ set }) => {
    set(apiSelectorRequestId, (n) => n + 1)
  },
})
export const sample = () => {
 const resetAtomValue = useResetRecoilState(atomValue)
 const resetApiSelectorRequestId = useResetRecoilState(apiSelector)
  return (
// resetAtomValue();でデフォルト値に戻してからapiSelector();でRequestseIDを更新することでAPIを送信
     <Button
      onClick={() => {
    resetAtomValue();
    apiSelector();
    }}
     >
     リセット
   </Button>
 }
)
1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0