我可以改变反冲原子效应中的其他状态吗



形势

我使用Recoil来管理React应用程序中的状态。我使用原子效果来备份反冲值与API。

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

详细信息

我有几个原子:

  1. 存储身份验证令牌的原子,用于与存储API通信
  2. 应用程序的各个部分的原子,我想保存在存储API上

为了执行API同步,我有一个apiStorageEffect原子效应。该效果使用使用getPromise的反冲存储身份验证令牌,并使用onSet处理程序转发更改。该处理程序在调用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. 是否可以从原子效应中修改原子OTHER而不是所讨论的原子/节点
  2. 原子效应是否有可能发出一个可以在React应用程序的其他地方立即处理的事件
  3. 原子效应有可能调用一种可以更广泛地修改反冲状态的方法吗

原子效应仍然很新(目前不稳定(。

你想要的行为自然会通过selector订阅所有相关原子来实现,并在那里处理效果。。。然而,选择器效应还不存在。

现在最简单的方法是将你的效果转换为一个使用效果钩执行操作的组件(在反冲文档中解释(。然后,该部件将被放置在RecoilRoot下方,以提供反冲状态。以下是一个基于您问题中信息的示例:

TS游乐场

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>
);
}

最新更新