如何使thunks独立于状态以使其可移植? [英] How to make thunks independent from state shape to make them portable?

查看:97
本文介绍了如何使thunks独立于状态以使其可移植?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用React和Redux开发了一个小型的独立Web应用程序,该应用程序托管在自己的Web服务器上。我们现在想要将此应用程序的大多数部分重用/集成到另一个React / Redux Web应用程序中。

I've developed a smallish standalone web app with React and Redux which is hosted on its own web server. We now want to reuse/integrate most parts of this app into another React/Redux web app.

理论上这应该可以很好地工作,因为我的所有React组件,reducer和大多数动作创作者都是纯粹的。但我有一些动作创建者返回依赖于应用程序状态的thunk。他们可能会发送异步或同步操作,但这不是问题。

In theory this should work quite nicely because all my React components, reducers and most action creators are pure. But I have a few action creators which return thunks that depend on the app state. They may dispatch async or sync actions, but that's not the issue here.

假设我的root reducer看起来像这样:

Let's say my root reducer looks like this:

const myAppReducer = combineReducers({
    foo: fooReducer,
    bar: barReducer,
    baz: bazReducer
});

我最复杂的动作创建者依赖于许多状态切片(幸运的是只有少数几个) :

and my most complex action creators depend on many state slices (luckily there are only a few of those):

const someAction = function () {
    return (dispatch, getState) => {
        const state = getState();

        if (state.foo.someProp && !state.bar.anotherProp) {
            dispatch(fetchSomething(state.baz.currentId);
        } else {
            dispatch(doSomethingSynchronous());
        }
    };
}

现在的问题是我的动作创建者希望所有内容都在状态对象的根目录中。但如果我们想将这个应用程序集成到另一个redux应用程序中,我们必须使用自己的密钥安装我的appReducer:

Now the problem is that my action creators expect everything to be inside the root of the state object. But if we want to integrate this app into another redux app we'll have to mount my appReducer with its own key:

// The otherAppReducer that wants to integrate my appReducer
const otherAppReducer = combineReducers({
    ....
    myApp: myAppReducer
});

这显然打破了我的行动返回thunk并需要读取app状态的创建者,因为现在所有内容都包含在myApp状态切片中。

This obviously breaks my action creators that return thunks and need to read app state, because now everything is contained in the "myApp" state slice.

我做了很多研究并思考如何正确这几天解决了这个问题,但似乎我就是这样第一个尝试将基于Redux的应用程序集成到另一个基于Redux的应用程序中。

I did a lot of research and thinking how to properly solve this the last few days, but it seems I'm the first one trying to integrate a Redux based app into another Redux based app.

到目前为止,我想到了一些黑客/想法:

A few hacks/ideas that came to mind so far:


  • 创建我自己的thunk类型,这样我就可以 instanceof 检查自定义thunk中间件并让它通过我的thunk自定义 getState 函数,然后返回正确的状态切片。

  • 使用自己的密钥挂载我的根减速器并使我的thunk依赖于那个键。

  • Create my own thunk type so I can do instanceof checks in a custom thunk middleware and make it pass my thunks a custom getState function which will then return the correct state slice.
  • Mount my root reducer with it's own key and make my thunks depend on that key.

到目前为止,我认为最好的方法是创建自己的自定义中间件,但我并不满意事实上,其他应用程序现在将依赖于我的中间件和自定义thunk类型。我认为必须采用更通用的方法。

So far I think the best approach would be to create my own custom middleware, but I'm not really happy with the fact that other apps will now depend on my middleware and custom thunk type. I think there must be a more generic approach.

任何想法/建议?你会如何解决这类问题?

Any ideas/suggestions? How would you solve this kind of problem?

推荐答案

您是否考虑过不依赖 store.getState( )?我会将操作与应用程序状态完全分离,并从调用操作的位置获取所需的数据。

Have you considered not depending on store.getState()? I would decouple the actions from the application state altogether and take in the data you need from where the actions are called.

例如:

const someAction = function (someProp, anotherProp, currentId) {
    return dispatch => {

        if (someProp && !anotherProp) {
            dispatch(fetchSomething(currentId);
        } else {
            dispatch(doSomethingSynchronous());
        }
    };
}

这使得操作完全可重用,你的缺点是现在必须在其他地方有这些信息。还有什么地方?如果方便的话,使用 this.context.store 道具连接,或者更好,通过对特定应用程序进行包装操作,所以:

This makes the actions totally reusable, with the downside of you having to now have that information elsewhere. Where else? If convenient, inside your component using this.context.store, or via props with connect, or maybe better, by having wrapper actions for your specific applications, so:

const someApplicationAction = () => {
  return (dispatch, getState) => {
    const { foo, bar, baz } = getState();

    dispatch(someGenericAction(foo.someProp, bar.anotherProp, baz.currentID));
  };
}

这篇关于如何使thunks独立于状态以使其可移植?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆