Redux之CURD

Redux的增加、更新、删除

集成Redux这一节,我们可以通过action、reducer、effect之间的配合,来得到相关数据。我们接下来继续学习Redux中如何增加、更新以及删除数据。

1. 增加—addOne

我们还是按照上一节通过id来获取用户数据的思路,利用redux集成增加功能。

  • 在actions.ts中添加创建用户action
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// content-hrmanager.actions.ts

/**
 * 增加用户信息
 */
export const createContentHrmanager = createAction(
  '[ContentHrmanager] Create ContentHrmanager',
  props<{ contentHrmanager: ContentHrmanagerEntity }>()
);

/**
 * 增加成功场合, 返回用户信息
 */
export const createContentHrmanagerSuccess = createAction(
  '[ContentHrmanager] Create ContentHrmanager Success',
  props<{ contentHrmanager: ContentHrmanagerEntity }>()
);
  • 在reducer.ts中追加分支条件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// content-hrmanger.reducer.ts

// 增加成功, 向store中存储最新的用户信息
on(
  ContentHrmanagerActions.createContentHrmanagerSuccess,
  (state, { contentHrmanager }) =>
    contentHrmanagerAdapter.addOne(contentHrmanager, {
      ...state,
      loaded: true,
      selectedId: contentHrmanager.id
    })
)
  • 在effects.ts中添加通过Id来查询用户信息
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 * 添加用户数据
 */
createContentHrmanagerById$ = createEffect(() =>
  this.dataPersistence.fetch(
    ContentHrmanagerActions.createContentHrmanager, {
      run: (action: any) => {
        // 取出参数id,查询用户数据
        return this.hrManagerService.addUser(action.contentHrmanager).pipe(
          // 正常,发出成功action
          map(data => (ContentHrmanagerActions.createContentHrmanagerSuccess({ contentHrmanager: data}))),
          // 异常,发出失败action
          catchError(err => of(ContentHrmanagerActions.loadContentHrmanagerFailure({ error: (err as HttpErrorResponse).message }))
          )
        );
      },
      onError: (action, error) => {
        console.error('Error', error);
        return ContentHrmanagerActions.loadContentHrmanagerFailure({ error });
      }
    }
  )
)
  • component中改造如下
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// form.component.ts

// add方法改造
const id = this.id.nativeElement.value;
const name = this.name.nativeElement.value;
const age = this.age.nativeElement.value;

const user = {
  'id': +id,
  'name': name,
  'age': +age
};

this.user$ = this.hrManagerFacade.selectedContentHrmanager$;
// 发出增加用户数据action
this.hrManagerFacade.dispatch(ContentHrmanagerActions.createContentHrmanager({contentHrmanager: user}));

上面做完后,我们在浏览器中测试结果如下:

2. 更新—upsertOne

如果store中entities存在该数据,则修改后并将结果返回

如果不存在,则向store中新增一条记录

  • 在actions.ts中添加创建用户action
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// content-hrmanager.actions.ts

/**
 * 更新用户信息
 */
export const updateContentHrmanager = createAction(
  '[ContentHrmanager] Update ContentHrmanager',
  props<{ id: number, contentHrmanager: ContentHrmanagerEntity }>()
);

/**
 * 更新成功场合, 返回用户信息
 */
export const updateContentHrmanagerSuccess = createAction(
  '[ContentHrmanager] Update ContentHrmanager Success',
  props<{ contentHrmanager: ContentHrmanagerEntity }>()
);
  • 在reducer.ts中追加分支条件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// content-hrmanger.reducer.ts

 // 更新成功, 向store中存储最新的用户信息
on(
  ContentHrmanagerActions.updateContentHrmanagerSuccess,
  (state, { contentHrmanager }) =>
  contentHrmanagerAdapter.upsertOne(contentHrmanager, {
    ...state,
    loaded: true,
    selectedId: contentHrmanager.id
  })
  • 在effects.ts中添加通过Id来查询用户信息
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 * 更新用户数据
 */
updateContentHrmanager$ = createEffect(() =>
  this.dataPersistence.fetch(
    ContentHrmanagerActions.updateContentHrmanager, {
      run: (action: any) => {
        // 取出参数id,更新用户数据
        return this.hrManagerService.updateUser(action.id, action.contentHrmanager).pipe(
          // 正常,发出成功action
          map(data => (ContentHrmanagerActions.updateContentHrmanagerSuccess({ contentHrmanager: data}))),
          // 异常,发出失败action
          catchError(err => of(ContentHrmanagerActions.loadContentHrmanagerFailure({ error: (err as HttpErrorResponse).message }))
          )
        );
      },
      onError: (action, error) => {
        console.error('Error', error);
        return ContentHrmanagerActions.loadContentHrmanagerFailure({ error });
      }
    }
  )
)
  • service中改造如下
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public updateUser(id: number, user: ContentHrmanagerEntity): Observable<ContentHrmanagerEntity> {
    return this.http.put(`${this.API}/${id}`, user).pipe(
      map(data => data as ContentHrmanagerEntity),
      catchError((err: HttpErrorResponse) => {
        if(err.status === 404) {
          return of(null);
        }
        return throwError(err);
      })
    );
  }
  • component中改造如下
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// form.component.ts

// add方法改造
const id = this.id.nativeElement.value;
const name = this.name.nativeElement.value;
const age = this.age.nativeElement.value;

const user: ContentHrmanagerEntity = {
  id: +id,
  name: name,
  age: +age
};

this.user$ = this.hrManagerFacade.selectedContentHrmanager$;
// 发出更新用户数据action
this.hrManagerFacade.dispatch(ContentHrmanagerActions.updateContentHrmanager({id: +id, contentHrmanager: user}));

上面做完后,我们在浏览器中测试结果如下:

3. 更新—updateOne

更新部分字段,类似PATCH

  • 在actions.ts中添加更新用户action
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// content-hrmanager.actions.ts

/**
 * 更新用户信息
 */
export const updateContentHrmanager = createAction(
  '[ContentHrmanager] Update ContentHrmanager',
  props<{ contentHrManager: Update<ContentHrmanagerEntity> }>()
);

/**
 * 更新成功场合, 返回用户信息
 */
export const updateContentHrmanagerSuccess = createAction(
  '[ContentHrmanager] Update ContentHrmanager Success',
  props<{ contentHrmanager: Update<ContentHrmanagerEntity> }>()
);
  • 在reducer.ts中追加分支条件
1
2
3
4
5
6
7
8
// content-hrmanger.reducer.ts

// 更新成功, 向store中存储最新的用户信息
on(
  ContentHrmanagerActions.updateContentHrmanagerSuccess,
  (state, action) =>
    contentHrmanagerAdapter.updateOne({id: +action.contentHrmanager.id, changes: action.contentHrmanager.changes}, state)
),
  • 在effects.ts中添加通过Id来更新用户信息
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
 * 更新用户数据
 */
updateContentHrmanager$ = createEffect(() =>
  this.dataPersistence.fetch(
    ContentHrmanagerActions.updateContentHrmanager, {
      run: (action: any) => {
        // 取出参数id,更新用户数据
        const id = action.contentHrManager.id;
        const changes = action.contentHrManager.changes;

        return this.hrManagerService.updateUser(id, changes).pipe(
          // 正常,发出成功action
          map(data => (ContentHrmanagerActions.updateContentHrmanagerSuccess({ contentHrmanager: data }))),
          // 异常,发出失败action
          catchError(err => of(ContentHrmanagerActions.loadContentHrmanagerFailure({ error: (err as HttpErrorResponse).message }))
          )
        );
      },
      onError: (action, error) => {
        return ContentHrmanagerActions.loadContentHrmanagerFailure({ error });
      }
    }
  )
)
  • service改造如下
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// hr-manager.service.ts

public updateUser(id: number, changes: Partial<ContentHrmanagerEntity>): Observable<any> {
  return this.http.put(`${this.API}/${id}`, changes).pipe(
    map(data => data),
    catchError((err: HttpErrorResponse) => {
      if(err.status === 404) {
        return of(null);
      }
      return throwError(err);
    })
  );
}
  • component中改造如下
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// form.component.ts

// 更新方法改造
const id = this.id.nativeElement.value;
const name = this.name.nativeElement.value;
const age = this.age.nativeElement.value;

const user: Update<ContentHrmanagerEntity> = {
  id: +id,
  changes: {
    name: name,
    age: +age
  }
};

this.user$ = this.hrManagerFacade.selectedContentHrmanager$;
// 发出更新用户数据action
this.hrManagerFacade.dispatch(ContentHrmanagerActions.updateContentHrmanager({contentHrManager: user}));

4. 删除—removeOne

  • 在actions.ts中添加删除用户action
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// content-hrmanager.actions.ts

/**
 * 删除用户信息
 */
export const deleteContentHrmanager = createAction(
  '[ContentHrmanager] Delete ContentHrmanager',
  props<{ id: number }>()
);

/**
 * 删除成功场合, 返回用户信息
 */
export const deleteContentHrmanagerSuccess = createAction(
  '[ContentHrmanager] Delete ContentHrmanager Success',
  props<{ contentHrmanager: ContentHrmanagerEntity }>()
);
  • 在reducer.ts中追加分支条件
1
2
3
4
5
6
7
8
// content-hrmanger.reducer.ts

// 删除成功, 从store中移除
on(
  ContentHrmanagerActions.deleteContentHrmanagerSuccess,
  (state, { contentHrmanager }) =>
  contentHrmanagerAdapter.removeOne(contentHrmanager.id, state)
),
  • 在effects.ts中添加通过Id来查询用户信息
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 * 删除用户数据
 */
deleteContentHrmanager$ = createEffect(() =>
  this.dataPersistence.fetch(
    ContentHrmanagerActions.deleteContentHrmanager, {
      run: (action: any) => {
        // 取出参数id,更新用户数据
        return this.hrManagerService.deleteUserById(action.id).pipe(
          // 正常,发出成功action
          map(data => (ContentHrmanagerActions.deleteContentHrmanagerSuccess({ contentHrmanager: data}))),
          // 异常,发出失败action
          catchError(err => of(ContentHrmanagerActions.loadContentHrmanagerFailure({ error: (err as HttpErrorResponse).message }))
          )
        );
      },
      onError: (action, error) => {
        console.error('Error', error);
        return ContentHrmanagerActions.loadContentHrmanagerFailure({ error });
      }
    }
  )
)
  • component中改造如下
1
2
3
4
5
6
7
8
// form.component.ts

// add方法改造
const id = this.id.nativeElement.value;

this.user$ = this.hrManagerFacade.selectedContentHrmanager$;
// 发出删除用户信息action
this.hrManagerFacade.dispatch(ContentHrmanagerActions.deleteContentHrmanager({ id: +id }));