【问题标题】:Actions/state to load data from backend从后端加载数据的操作/状态
【发布时间】:2018-10-03 03:11:21
【问题描述】:

我刚刚开始尝试使用ngxs,但从我目前的阅读情况来看,我并没有 100% 清楚我应该在哪里回调我的 API 以保存和读取数据(我见过的所有示例都是不这样做,或使用一些模拟)。

例如我创建了一个维护项目列表的状态。当我想添加一个项目时,我将“AddItem”操作发送到商店,在那里我将该新项目添加到状态。这一切正常 - 问题是插入将项目发布到服务器的调用的合适位置在哪里?

我是否应该在我的操作实现中调用 API,即在我更新商店的商品列表之前。

或者我应该在我的 Angular 组件中调用 API(通过服务),然后在收到响应时分派“添加项目”操作?

我对这个领域很陌生,所以这些方法的任何指导或优缺点都会很棒。

【问题讨论】:

    标签: angular ngxs


    【解决方案1】:

    如果您想将效果与商店分开,您可以定义一个基本状态类:

    @State<Customer>( {
        name: 'customer'
    })
    export class CustomerState {
        constructor() { }
    
        @Action(ChangeCustomerSuccess)
        changeCustomerSuccess({ getState, setState }: StateContext<Customer>, { payload }: ChangeCustomerSuccess ) {
            const state = getState();
           // Set the new state. No service logic here.
           setState( {
               ...state,
               firstname: payload.firstname, lastname: lastname.nachname
           });
        }
    }
    

    然后您将从该状态派生并将您的服务逻辑放入派生类中:

    @State<Customer>({
        name: 'customer'
    })
    export class CustomerServiceState extends CustomerState {
    
        constructor(private customerService: CustomerService, private store: Store) {
            super();
        }
    
        @Action(ChangeCustomerAction)
        changeCustomerService({ getState, setState }: StateContext<Customer>, { payload }: ChangeCustomerAction) {
    
            // This action does not need to change the state, but it can, e.g. to set the loading flag.
            // It executes the (backend) effect and sends success / error to the store.
    
            this.store.dispatch( new ChangeCustomerSuccess( payload ));
        }
    }
    

    我在浏览的任何 NGXS 示例中都没有看到这种方法,但我一直在寻找一种方法来分离这两个问题 - UI 和后端。

    【讨论】:

      【解决方案2】:

      最好的地方是你的动作处理程序。

      import { HttpClient } from '@angular/common/http';
      import { State, Action, StateContext } from '@ngxs/store';
      import { tap, catchError } from 'rxjs/operators';
      
      //
      // todo-list.actions.ts
      //
      export class AddTodo {
        static readonly type = '[TodoList] AddTodo';
        constructor(public todo: Todo) {}
      }
      
      
      //
      // todo-list.state.ts
      //
      export interface Todo {
        id: string;
        name: string;
        complete: boolean;
      }
      ​
      export interface TodoListModel {
        todolist: Todo[];
      }
      ​
      @State<TodoListModel>({
        name: 'todolist',
        defaults: {
          todolist: []
        }
      })
      export class TodoListState {
      
        constructor(private http: HttpClient) {}
      ​
        @Action(AddTodo)
        feedAnimals(ctx: StateContext<TodoListModel>, action: AddTodo) {
      
          // ngxs will subscribe to the post observable for you if you return it from the action
          return this.http.post('/api/todo-list').pipe(
      
            // we use a tap here, since mutating the state is a side effect
            tap(newTodo) => {
              const state = ctx.getState();
              ctx.setState({
                ...state,
                todolist: [ ...state.todolist, newTodo ]
              });
            }),
            // if the post goes sideways we need to handle it
            catchError(error => window.alert('could not add todo')),
          );
        }
      }
      

      在上面的示例中,我们没有明确的操作来返回 api,我们根据 AddTodo 操作响应改变状态。

      如果您愿意,可以将其拆分为三个更明确的操作,

      AddTodoAddTodoCompleteAddTodoFailure

      在这种情况下,您需要从 http 帖子中调度新事件。

      【讨论】:

      • 感谢您的快速回复 - 我将在此处针对我的应用程序尝试您的示例。同样,我假设我们将定义一个“LoadTodos”动作,并让该动作处理程序从服务器加载初始数据(因为默认状态将为空)。听起来对吗?
      • 您可以使用 NgxsOnInit 生命周期事件来调度 LoadTodos 操作。然后为此添加一个动作处理程序。文档中有你如何做到这一点。
      • 知道了 - 我现在在文档的 Advanced -> LifeCycle 部分看到了这一点(诚然,我还没有阅读 Advanced 下的所有内容)。再次感谢您的帮助,我非常喜欢 NGXS 到目前为止所看到的内容
      猜你喜欢
      • 2014-05-04
      • 1970-01-01
      • 2021-07-27
      • 1970-01-01
      • 1970-01-01
      • 2019-09-19
      • 1970-01-01
      • 1970-01-01
      • 2012-06-13
      相关资源
      最近更新 更多