跳到主要内容

计算属性

单个 Entity 的计算​

Entity 类就是普通的类,因此任何常见的派生数据都可以直接作为 getter 添加到类本身上。

import { All, Entity, Query } from '@data-client/rest';

class User extends Entity {
id = '';
firstName = '';
lastName = '';
username = '';
email = '';

get fullName() {
return `${this.firstName} ${this.lastName}`;
}

static key = 'User';
}

如果计算开销较大,可以随意加上一些记忆化。

import { All, Entity, Query } from '@data-client/rest';
import memoize from 'nano-memoize';

class User extends Entity {
truelyExpensiveValue = memoize(() => {
// compute that expensive thing!
});
}
提示

如果你只是想把某个字段反序列化为更有用的形式,例如 Temporal.Instant 或 BigNumber,可以使用声明式的 static schema。

import { All, Entity, Query } from '@data-client/rest';
import BigNumber from 'bignumber.js';

class User extends Entity {
id = '';
firstName = '';
lastName = '';
createdAt = Temporal.Instant.fromEpochMilliseconds(0);
lifetimeBlinkCount = BigNumber(0);

static key = 'User';

static schema = {
createdAt: Temporal.Instant.from,
lifetimeBlinkCount: BigNumber,
};
}

全局计算​

Query 可用于基于多个 Entity 计算派生数据。我们通常把这类计算称为聚合。

import { All, Query, schema } from '@data-client/rest';
import { useQuery, useSuspense } from '@data-client/react';
import { UserResource, User } from './resources/User';

const getUserCount = new Query(
  new All(User),
  (entries, { isAdmin } = {}) => {
    if (isAdmin !== undefined)
      return entries.filter(user => user.isAdmin === isAdmin).length;
    return entries.length;
  },
);

function UsersPage() {
  useSuspense(UserResource.getList);
  const userCount = useQuery(getUserCount);
  const adminCount = useQuery(getUserCount, { isAdmin: true });
  // this should never happen since we suspense but typescript does not know that
  if (userCount === undefined) return null;
  return (
    <div>
      <div>Total users: {userCount}</div>
      <div>Total admins: {adminCount}</div>
    </div>
  );
}
render(<UsersPage />);
结果
Store▶