Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在Redux中放置特定于上下文的多步骤异步逻辑的位置_Javascript_Reactjs_Redux_Redux Thunk - Fatal编程技术网

Javascript 在Redux中放置特定于上下文的多步骤异步逻辑的位置

Javascript 在Redux中放置特定于上下文的多步骤异步逻辑的位置,javascript,reactjs,redux,redux-thunk,Javascript,Reactjs,Redux,Redux Thunk,tl;dr我想知道在redux体系结构中如何放置特定于上下文的多步骤异步回调逻辑,以及我是否正确使用下面提供的示例代码。所谓“多步骤”和“特定于上下文”我通常指的是由某些用户操作(onclick等)启动的服务器调用,其中逻辑可能仅与给定组件相关(例如成功时重定向到给定路由) 关于代码的redux文档具有副作用: 一般来说,Redux建议带有副作用的代码应该是动作创建过程的一部分。虽然该逻辑可以在UI组件内部执行,但将该逻辑提取到可重用函数中通常是有意义的,这样就可以从多个位置调用相同的逻辑,换句

tl;dr我想知道在redux体系结构中如何放置特定于上下文的多步骤异步回调逻辑,以及我是否正确使用下面提供的示例代码。所谓“多步骤”和“特定于上下文”我通常指的是由某些用户操作(onclick等)启动的服务器调用,其中逻辑可能仅与给定组件相关(例如成功时重定向到给定路由)

关于代码的redux文档具有副作用:

一般来说,Redux建议带有副作用的代码应该是动作创建过程的一部分。虽然该逻辑可以在UI组件内部执行,但将该逻辑提取到可重用函数中通常是有意义的,这样就可以从多个位置调用相同的逻辑,换句话说,就是一个action creator函数

虽然这看起来很好,但我不能完全确定将对我的路由组件的调用放在其中是否“正确”,因为这些操作创建者通常看起来非常通用,并且触发到应用程序中其他资源的路由通常非常依赖于上下文

我还发现,将这些完全不同的野兽放在与“干净”同步动作创建者相同的文件(
foo model/actions.js
)中有点奇怪,它们异步触发动作创建者并分派生成的动作。这是正确的地方吗?当阅读Redux上的教程时,它们似乎生活在一起

示例代码非常简单,基本上描述了以下步骤:

  • 在用户单击时,使用一些参数调用函数
  • 此函数调用另一个异步函数(如网络调用)
  • 异步调用完成后,触发到另一页的路由操作
  • 背景:我想逐步重构Meteor项目,将所有特定于Meteor的部分移出React组件,最终将Meteor前后部分替换为其他部分。由于大约有50KLOC,我无法一次性完成这项工作,因此我正在逐步地一次通过一条路线,希望最终得到一个标准的React+Redux+ReduxRouter包。在当前的代码路由中,数据获取和呈现在每个组件中都有一定程度的相互交织,我很难找到将多步骤异步逻辑放在何处,例如下面的示例

    关于我正在努力解决的堆栈的详细信息:

    • 用于路由的FlowRouter
    • Meteor/MiniMongo用于数据突变和检索
    • 对于高阶组件
    MyContainer组件中的旧Meteor代码

    新的redux代码-移动到actions.js

    在这一点上,我试图保持实现的直截了当(没有额外的DEP),以了解基础。使用
    redux-thunk
    redux-actions
    redux-saga
    的“简化”需要稍后才能实现。仿效


    在我使用Redux的经验中,我没有发现在action Creator中放置异步调用有任何问题。我认为
    redux-thunk
    或其他一些中间件非常有用,即使是对于一个简单的设置

    我要补充的唯一一点是,我觉得您的示例代码可读性不强

    就我个人而言,我喜欢,但也只是将动作类型、动作创建者和还原者保存在单独的文件中,这将有助于提高清晰度


    希望这能有所帮助。

    根据我使用Redux的经验,我没有发现将异步调用放在动作创建者内部有任何问题。我认为
    redux-thunk
    或其他一些中间件非常有用,即使是对于一个简单的设置

    我要补充的唯一一点是,我觉得您的示例代码可读性不强

    就我个人而言,我喜欢,但也只是将动作类型、动作创建者和还原者保存在单独的文件中,这将有助于提高清晰度


    希望这能有所帮助。

    我明白你的意思,你想有一种方法来划分你的行为,对吗?将执行同步代码、异步代码、记录器等的操作

    就我个人而言,我使用一些命名约定。如果我必须调度一个必须获取一些数据的操作,我将其称为
    REQUEST\u data
    。如果必须将从服务器到达的一些数据存储到
    ReduxStore
    ,我称之为
    store\u data


    我没有一个具体的模式。我还必须指出,我根据功能划分了代码库,因此我定义动作的模块非常小且整洁

    我明白你的意思,你想有一种方法来划分和分类你的动作,对吗?将执行同步代码、异步代码、记录器等的操作

    就我个人而言,我使用一些命名约定。如果我必须调度一个必须获取一些数据的操作,我将其称为
    REQUEST\u data
    。如果必须将从服务器到达的一些数据存储到
    ReduxStore
    ,我称之为
    store\u data


    我没有一个具体的模式。我还必须指出,我根据功能划分了代码库,因此我定义动作的模块非常小且整洁

    ,正如您在评论中所指出的,Dan Abramov在他的回答中讨论了在Redux中处理异步工作背后的许多想法。他还用英语写了另一个极好的答案

    您可能需要阅读my类别中的其他一些文章,以便更好地了解在Redux中处理异步逻辑的方法


    一般来说,听起来您可能想使用“sagas”或“observables”来管理一些异步逻辑和工作流。异步行为的Redux中间件种类繁多——我在博客文章中总结了主要类别和最流行的库。在一篇名为的帖子中,也有一些关于一个非常解耦的基于saga的Redux架构的有趣想法。

    正如您在评论中提到的,Dan Abramov在他的回答中讨论了在Redux中处理异步工作背后的许多想法
    // triggered as onClick={(e) => this.saveEncounter(e.target.value)}
    // in render()
    const saveEncounter = (encounter) => {
        Meteor.call('createEncounter', encounter, handleSaveResult);
      }
    };
    
    const handleSaveResult = (err, encounterId) => {
      if (err) {
        this.setState({errorMessages: err});
      } else {
        // route to another page
        NavigationActions.goTo('encounter', {encounterId: this.props.encounter._id || encounterId});
      }
    }
    
    export const saveEncounter = (encounter) => {
    
        function handleSave(err, encounterId) {
            if (err) {
                dispatch(createEncounterFailure(err), encounter);
            } else {
                dispatch(createEncounterSuccess(encounterId));
            }
        }
    
        dispatch(createEncounterRequest(encounter));
        Meteor.call('createEncounter', encounter, handleSave);
    }
    
    
    // simple sync actions creators
    export const CREATE_ENCOUNTER_REQUEST = 'CREATE_ENCOUNTER_REQUEST';
    function createEncounterRequest(encounter) {
        return {
            type: CREATE_ENCOUNTER_REQUEST,
            encounter
        };
    }
    export const CREATE_ENCOUNTER_FAILURE = 'CREATE_ENCOUNTER_FAILURE';
    function createEncounterFailure(error, encounter) {
        return {
            type: CREATE_ENCOUNTER_FAILURE,
            error,
            encounter
        };
    }
    export const CREATE_ENCOUNTER_SUCCESS = 'CREATE_ENCOUNTER_SUCCESS';
    function createEncounterSuccess(encounterId) {
        return {
            type: CREATE_ENCOUNTER_SUCCESS,
            encounterId
        };
    }