ngxs 状态运算符插入或替换数组中的项目(upsert)

Mic*_*ker 3 ngxs

我正在尝试用现有的 ngxs 状态运算符替换或插入数组项(upsert)。我目前正在使用以下 iif 语句。有没有更简单的方法来做到这一点?

setState(
  patch({
    contractList: iif<Contract[]>(
      contractList=>
        contractList.some(
          contract =>
            contract.id === contractId
        ),
      updateItem<Contract>(
        contract =>
          contract.id === contractId,
        patch(loadedContract)
      ),
      insertItem<Contract>(loadedContract)
    )
  })
)
Run Code Online (Sandbox Code Playgroud)

ove*_*ity 5

状态操作员存在,但这并不意味着你被迫使用它们,对吧。有一个叫做Immutability Helpers的方法。它将在 1-2 周内发布到主站点。

如果我们谈论状态运算符,那么可以创建自定义运算符,这是某种分解:

function insertOrUpdateContract(id: string, loadedContract?: Contract) {
  return iif<Contract[]>(
    contracts => contracts.some(contract => contract.id === id),
    updateItem(contract => contract.id === id, patch(loadedContract)),
    insertItem(loadedContract)
  );
}
Run Code Online (Sandbox Code Playgroud)

因此,您的操作处理程序中的代码将会更少,并且更加具有自我描述性:

ctx.setState(
  patch({ contractList: insertOrUpdateContract(contractId, loadedContract) })
);
Run Code Online (Sandbox Code Playgroud)

否则,您可以使用immer库或其他首选的东西,这将节省更多代码:

import { produce } from 'immer';

const state = produce(ctx.getState(), draft => {
  const index = draft.contractList.findIndex(contract => contract.id === contractId);
  // It exists then let's update
  if (index > -1) {
    draft.contractList[index] = loadedContract;
  } else {
    draft.contractList.push(loadedContract);
  }
});

ctx.setState(state);
Run Code Online (Sandbox Code Playgroud)

当然immer是该项目的一个附加包,但它非常轻量级。它提供了更具声明性的方式来执行此类不可变更新。选择最适合您的!

当涉及到如此复杂的状态更新时,我会停止使用一些不变性助手。