为什么 React Flow 拒绝这种方法?

Why does React Flow reject this approach?

我正在使用 Context APIReact Hooks 构建一个 React 应用程序。我正在尝试遵循最佳实践。为此,我正在使用 Flow 并努力遵守其警告。

我有一种情况,一旦用户登录,我想在我构建的 SessionContext 中存储一些关于该用户的数据。鉴于现在只有 3 条数据,而且它们都是原始数据,我认为只有一个 Reducer Action 是有意义的:

export const sessionReducer = (state: SessionState, action: SessionAction) => {
  switch (action.type) {
    case UPDATE_SESSION_PROP: {
      return {
        ...state,
        [action.propName]: action.payload
      };
    }

    default: {
      return state;
    }
  }
}

以下是我创建的用于说明 3 种数据类型的操作类型:

export type UserEmailAction = {type: 'UPDATE_SESSION_PROP',
                               propName: 'currentUserEmail',
                               payload: string};

export type UserAccessLevelAction = {type: 'UPDATE_SESSION_PROP',
                                     propName: 'currentUserAccessLevel',
                                     payload: number};

export type CurrentCompanyNameAction = {type: 'UPDATE_SESSION_PROP',
                                        propName: 'currentCompanyName',
                                        payload: string};

在我的 SessionContext 中,我将这 3 种 Action 类型组合如下,然后从中定义一个 Dispatch 类型:

export type SessionAction = 
  | UserEmailAction
  | UserAccessLevelAction
  | CurrentCompanyNameAction;

type Dispatch = (action: SessionAction) => void;

在此代码中 sessionReducer 之上有 4 条警告消息:

const [state: SessionState, dispatch: Dispatch] = useReducer(sessionReducer, defaultState);

消息类似于:"Cannot call useReducer with sessionReducer bound to reducer because number [1] is incompatible with string [2] in property currentCompanyName of the return value."

我是否错误地定义了 Action 类型,或者 Flow 是否不够智能来区分 3 种模式?顺便说一句,这种方法似乎在 运行.

时工作正常

Flow 不够智能。但是您可以使用流程可以理解的不同方法:

type SessionState = {
  currentUserEmail: string,
  currentUserAccessLevel: number,
  currentCompanyName: string,
};

type SessionAction = {
  type: 'UPDATE_SESSION_PROP',
  payload: $Shape<SessionState>,
};

const sessionReducer = (state: SessionState, action: SessionAction) => {
  switch (action.type) {
    case UPDATE_SESSION_PROP: {
      return {
        ...state,
        ...action.payload
      };
    }

    default: {
      return state;
    }
  }
}

https://flow.org/try/#0JYWwDg9gTgLgBAbzgVwM4FMBK6AmyDG6UcAvnAGZQQhwDkU6AhvjLQNwBQH+EAdqvACqABQAiAQQAqAUQD6AZWnz5ASQDyAOVnDMa4XAC8dERJkKlqzdt3D2XGAE8w6OPPSpUwPvJiMYLowQOODh8ZCgGXhhBDChpEEZgABsALjgBKGBeAHMAGmDQ8Mjo2PF8Qg8AGXQAN3RUuF5kEAAjInyQsIj0KIBhajBGXgcNRhB0NIysvI4STg50AA9IWDhHZ1d3Tz4ymC9eQ0QC9YnjMSk5RWV1LR09Wg64QYckiEYcNIASeQALRmcADxuDz7Hx+dAAPnyc3sThcomAqEGMHwP0OAApmHs+GlgdteLt9gBKQwQuA1CDAHDzHDofBJRgMcmMuC08iMZBJGBg-y4rag3z+eY8fjwDAgvjYPCEYhGdECcF8iW8HnoXJwLH7JX4wl8EkGMlBEKoADuwBRaMxLH2ADoTiSjSFQowMHATBdzNcrHdhGlHU64AwYOEDv6A3AbZGFf5HuGI5HNXwbc9Xu8CgGYRmuAG2RyuX7006gyH0oL0JwsyESLMuCKBHAANrR054gXg9U4RHI1FpBFIvyogC6hzQWFwBCI8v5kvHMo76HZnO5ZaJbCAA

它也会减少整体代码量,所以我认为这不是太糟糕。