后坐力 JS - 摆脱重新渲染我的应用程序的悬念



我正在我目前正在构建的React框架中试验Recoil。在我的用例中,应用程序将根据用户活动生成一个操作对象,然后将其发送到服务器,从那里获取应用程序状态。

该动作存储在后坐力atom中。我正在使用接受操作并从服务器获取状态的反冲selectorFamily。以下是我实际正在做的事情的琐碎示例(代码在打字稿中(:

export const MyActionAtom = atom<MyAction|undefined>({
key: "MyActionAtom",
default: undefined
});
const MyStateSelectorFamily = selectorFamily({
key: 'MyStateSelectorFamily',
get: (action: MyAction|undefined) => async ({get}) => {        
if (action) {
return await getStateFromServer(action);
}
return SomeFallbackState;
}
});
const MyStateSelector = selector({
key: 'MyStateSelector ',
get: ({get}) => {
return get(MyStateSelectorFamily(get(MyActionAtom)));
}
});

function App() {
const appState = useRecoilValue(MyStateSelector);
return (
<RecoilRoot>
<React.Suspense fallback={<div>Loading...</div>}>
<MyApp state={appState} />
</React.Suspense>
</RecoilRoot>
);
}

在这里,MyApp是一个反应组件,它将基于 appState 呈现应用程序的整个视图树。

现在,从直接或间接MyApp子组件中,可能会触发另一个操作:

const setMyAction = useSetRecoilState(MyActionAtom);
setMyAction(...);

setMyAction的结果在值上略有偏差,而不是我初始化应用程序的初始状态。因此,我只想重新渲染依赖于更改状态的组件。

但是,我的整个视图树都会更新。我怀疑的原因是React.Suspense正在用回退替换 dom,直到返回操作的响应(请注意,MyStateSelectorFamily是异步的,因为状态是作为承诺返回的(。

在一个更像 redux 的世界中,我会在解决承诺后触发我的请求并调度状态更改(我打算以不同于React.Suspense为我做的事情的方式处理加载状态(。

有没有办法防止我的应用重新呈现?我已经看到了使用后坐力Loadables以避免React.Suspense的例子,但是当可加载对象处于loading状态时,我正在努力获得旧的应用程序状态。

<小时 />

更新

随着我进一步的实验,我能够让它通过调度方法模仿减速器方法:

  1. 我去掉了动作原子,MyStateSelectorFamily改成了原子本身:

    const MyStateAtom = atom({
    key: 'MyStateAtom ',
    default: SomeFallbackState
    });
    
  2. 我用自定义钩子替换了更改状态的组件中的setMyAction(...);部分:

    // in some dedicated ts file:
    export const useAction = () => {
    const dispatch = useSetRecoilState(MyStateAtom);
    return useCallback(async (action: MyAction) => {
    await getStateFromServer(action).then(dispatch);
    }, [dispatch]);
    };
    
  3. 我在组件中使用钩子:

    export const SomeComponent = (props: SomeProps) => {
    const dispatchAction = useAction();
    // other logic
    const action: MyAction = ... // create the appropriate action
    dispatchAction(action);
    return (...);
    };
    

好吧,这似乎可以按照我想要的方式工作,并且更接近我以前使用 redux 的代码库,所以我比以前的selectorFamily方法更喜欢它。但是,我经常在控制台中看到反应警告:

Warning: Cannot update a component (`Batcher`) while rendering a 
different component (`SomeComponent`) ....

我的应用是 SPA 应用,警告在初始加载时打印。然后它可以在没有可观察到的问题的情况下工作。我想知道我是否可以解决警告的原因 - 这个Batcher似乎是一个后坐力的事情,我想我做不好的事情来打破它。

此处讨论了弹出警告的原因。这基本上是Recoil内部的逻辑流错误,将在下一个版本中修复。 目前,您无法对此执行任何操作,但它仅在开发模式下弹出,而在生产模式下,警告将被忽略。

相关内容

  • 没有找到相关文章

最新更新