【问题标题】:Can I change other pieces of state in a Recoil Atom Effect我可以在 Recoil Atom 效果中更改其他状态吗
【发布时间】:2022-01-15 22:20:55
【问题描述】:

情况

我正在使用Recoil 来管理React 应用程序中的状态。我正在使用Atom Effects 通过 API 备份反冲值。

当我的 Atom 检测到身份验证令牌有问题时,我希望它以某种方式将该问题传达给应用程序的其余部分,以便应用程序可以更新状态。

细节

我有几个原子:

  1. 一个存储身份验证令牌的原子,在与存储 API 通信时使用。
  2. 我想保存在该存储 API 上的各种应用程序的原子。

为了执行 API 同步,我有一个 apiStorageEffect Atom Effect。该效果使用使用getPromise 的recoil 存储的身份验证令牌,并使用onSet 处理程序转发更改。该处理程序在调用 save 方法时使用令牌。 save 方法可以检测身份验证何时失败。

当身份验证失败时,我需要触发注销事件(将令牌设置为 null,并将一系列原子重置为其默认值)。

这里是存储效果的最小版本:

const apiStorageEffect = (key) => async ({
    onSet,
    getPromise,
}) => {
    const authToken = await getPromise(authTokenAtom)
    if (!authToken) { return }

    onSet(async (newValue) => {
        const result = await saveToApiStorage(key, newValue, authToken)
        if (result.failed) {
            // INSERT CODE TO TRIGGER LOGOUT HERE
        }
    })
}

问题

我可以想到一些从效果中触发注销的可能路径,但它们都涉及以某种方式将信息在受影响的原子之外发送到主应用程序。

  1. 是否可以在原子效果中修改原子其他而不是相关原子/节点?
  2. 原子效果是否可以发出可以在 React 应用程序的其他地方立即处理的事件?
  3. 原子效应是否可以调用可以更广泛地修改反冲状态的方法?

【问题讨论】:

    标签: node.js reactjs recoiljs


    【解决方案1】:

    Atom effects 仍然很新(目前不稳定)。

    您希望的行为自然会通过selector 订阅所有相关原子并在那里处理效果来实现......但是,选择器效果还不存在。

    现在最直接的方法是将您的效果转换为使用effect hook 执行操作的组件(在反冲docs 中进行了解释)。然后该组件将被放置在提供反冲状态的RecoilRoot 下方。以下是基于您问题中的信息的示例:

    TS Playground

    import {useCallback, useEffect} from 'react';
    import {atom, RecoilRoot, useRecoilValue, useResetRecoilState} from 'recoil';
    
    declare function saveToApiStorage (
      key: string,
      data: { value1: number; value2: number; },
      authToken: string,
    ): Promise<{failed: boolean}>;
    
    export const authTokenState = atom<string | null>({
      key: 'authToken',
      default: null,
    });
    
    // the key used in your effect
    export const keyState = atom({key: 'key', default: ''});
    // some bit of state for the API
    export const value1State = atom({key: 'value1', default: 0});
    // another one
    export const value2State = atom({key: 'value2', default: 0});
    
    // this is the converted effect component
    export function ApiStorageEffect (): null {
      const key = useRecoilValue(keyState);
      const authToken = useRecoilValue(authTokenState);
      const value1 = useRecoilValue(value1State);
      const value2 = useRecoilValue(value2State);
      const resetAuthToken = useResetRecoilState(authTokenState);
      const resetValue1 = useResetRecoilState(value1State);
      const resetValue2 = useResetRecoilState(value2State);
    
      const updateStorage = useCallback(async () => {
        if (!authToken) return;
    
        const result = await saveToApiStorage(key, {value1, value2}, authToken);
    
        if (result.failed) {
          resetAuthToken();
          resetValue1();
          resetValue2();
        }
      }, [
        authToken,
        key,
        resetAuthToken,
        resetValue1,
        resetValue2,
        value1,
        value2,
      ]);
    
      // use void operator for correct return type
      useEffect(() => void updateStorage(), [updateStorage]);
      return null;
    }
    
    // include underneath the recoil root
    function App () {
      return (
        <RecoilRoot>
          <ApiStorageEffect />
          {/* rest of app... */}
        </RecoilRoot>
      );
    }
    
    

    【讨论】:

      猜你喜欢
      • 2021-02-01
      • 1970-01-01
      • 2019-10-16
      • 1970-01-01
      • 1970-01-01
      • 2018-11-01
      • 1970-01-01
      • 2018-10-19
      • 2020-06-13
      相关资源
      最近更新 更多