【问题标题】:Flow complaining about action union type in reducer流抱怨减速器中的动作联合类型
【发布时间】:2017-12-29 19:59:32
【问题描述】:

Flow 为每个参数(action.location、action.weatherResult 和 action.error)引发 3 个错误(未找到属性)。我发现的唯一解决方案是不联合,并且只有一种操作类型,其中包含 3 个不同的属性作为可选属性,但这些属性不是可选的,所以它不能解决我的问题。

动作

// @flow
import actionTypes from './index';    

export type FetchWeatherStartAction = {
  type: string,
  location: string
};    

export type FetchWeatherSuccessAction = {
  type: string,
  weatherResult: ?string
};    

export type FetchWeatherFailAction = {
  type: string,
  error: string | false
};    

export type WeatherAction = FetchWeatherStartAction | FetchWeatherSuccessAction | FetchWeatherFailAction;    

const fetchWeatherStart = (location: string): FetchWeatherStartAction => ({
  type: actionTypes.WEATHER_FETCH_START,
  location
});    

const fetchWeatherSuccess = (weatherResult: ?string): FetchWeatherSuccessAction => ({
  type: actionTypes.WEATHER_FETCH_SUCCESS,
  weatherResult
});    

const fetchWeatherFail = (error: string | false): FetchWeatherFailAction => ({
  type: actionTypes.WEATHER_FETCH_FAIL,
  error
});    

export {
  fetchWeatherStart,
  fetchWeatherSuccess,
  fetchWeatherFail
}

动作类型

// @flow
const actionTypes = {
  WEATHER_FETCH_START: 'WEATHER_FETCH_START',
  WEATHER_FETCH_SUCCESS: 'WEATHER_FETCH_SUCCESS',
  WEATHER_FETCH_FAIL: 'WEATHER_FETCH_FAIL'
}    

export default actionTypes;

减速器

// @flow
import actionTypes from './../actions';
import type { WeatherAction } from './../actions/weather';    

/*export type WeatherActionType = {
  type: string,
  error?: boolean | string,
  weatherResult?: string | null,
  location?: string
};*/    

export type WeatherStateType = {
  location: string,
  fetchedFromServer: boolean,
  isFetching: boolean,
  fetchError: boolean | string,
  weatherResult: ?string
};    

const defaultState: WeatherStateType = {
  location: 'Barcelona',
  fetchedFromServer: false,
  isFetching: false,
  fetchError: false,
  weatherResult: null
};    

const weather = (state: WeatherStateType = defaultState, action: WeatherAction): WeatherStateType => {    

  switch (action.type) {    

    case actionTypes.WEATHER_FETCH_START:
      return {
        ...state,
        isFetching: true,
        fetchError: false,
        location: action.location
      };    

    case actionTypes.WEATHER_FETCH_SUCCESS:
      return {
        ...state,
        fetchedFromServer: true,
        isFetching: false,
        fetchError: false,
        weatherResult: action.weatherResult
      };    

    case actionTypes.WEATHER_FETCH_FAIL:
      return {
        ...state,
        fetchedFromServer: false,
        isFetching: false,
        fetchError: action.error
      };    

    default:
      return state;
  }    

};    

export default weather;

【问题讨论】:

  • 请包含足够的导入的actionTypes,以便有人可以运行它来重现您的确切错误。

标签: javascript reactjs redux react-redux flowtype


【解决方案1】:

您正试图依赖实际上并未在您的类型中编码的类型信息。

例如在FetchWeatherStartAction的定义中:

export type FetchWeatherStartAction = {
  type: string,
  location: string
};

type 被声明为string。任何字符串。

但稍后,在这个 switch 案例中:

switch (action.type) {    
    case actionTypes.WEATHER_FETCH_START:
        ...
        action.location
        ...

您希望 Flow 知道 FetchWeatherStartActionWeatherAction 枚举的唯一可能替代方案,它可以将 'WEATHER_FETCH_START' 作为其 type 属性的值。仅基于类型,any 动作的类型可能有 any 值。我们唯一可以确定的是它是一个字符串。

解决方案是将您的操作变体定义为具有更具体的类型,其中包含它们的合法值。

export type FetchWeatherStartAction = {
  type: 'WEATHER_FETCH_START',
  location: string
};    

export type FetchWeatherSuccessAction = {
  type: 'WEATHER_FETCH_SUCCESS',
  weatherResult: ?string
};    

export type FetchWeatherFailAction = {
  type: 'WEATHER_FETCH_FAIL',
  error: string | false
};  

当您检查 type === 'WEATHER_FETCH_START' 时,Flow 可以确定实际类型是 FetchWeatherStartAction。这是可能的,因为它已经知道 action 是一个 WeatherAction 并且 WeatherAction 是一个枚举,只有这三个可能的值。

不幸的是,您必须重复字符串文字,而不是引用常量。我知道人们对此感到不安,但在这种情况下,我会争辩说,魔术常量被认为是不好的做法的所有原因都由 Flow 的类型检查处理。在 Javascript 中,使用语法标识符访问字段在语义上与通过字符串名称访问字段没有区别。

【讨论】:

  • 这是有道理的,我试图将常量分配为“类型”的类型,但这确实不起作用。我会考虑用字符串文字替换常量。感谢您的解释。
【解决方案2】:

万一有人偶然发现了这个问题。

根本原因:Flow 将在您进行函数调用时删除对类型的所有改进。

解决方案:在调用函数之前访问参数

例如,在你的情况下,reducer 可以这样写:

const reducer = (state: {}, action: WeatherAction): WeatherStateType => {
    switch (action.type) {
      case actionTypes.WEATHER_FETCH_START:
          const {location} = action;
          return { ...state, isFetching: true, fetchError: false, location: location};
      case actionTypes.WEATHER_FETCH_SUCCESS:
          const {weatherResult} = action;
          return {...state, fetchedFromServer: true, isFetching: false, fetchError: false,, weatherResult: weatherResult};
      case actionTypes.WEATHER_FETCH_FAIL:
          const {error} = action;
          return {...state. fetchedFromServer: false, isFetching: false, fetchError: action.error};
      default: 
          return state
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-01
    • 2019-10-23
    相关资源
    最近更新 更多