2017-07-24 169 views
0

Flow爲每個參數(action.location,action.weatherResult和action.error)引發3個錯誤(未找到屬性)。我發現的唯一的解決方案是不結合,只有一個動作類型與3個不同的屬性作爲可選maybes,但屬性不是可選的,所以它不能解決我的問題。Flow抱怨Reducer中的action union類型

操作

// @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; 
+0

請包括足夠的導入'actionTypes',以便有人可以運行它來重現您的確切錯誤。 –

回答

2

您正試圖依靠I型信息實際上沒有在你的類型中編碼。

例如在FetchWeatherStartAction定義:

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

type被宣佈爲一個string。任何字符串。

但後來,在這種開關情況:

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

你期望流量知道FetchWeatherStartActionWeatherAction枚舉這可能會對'WEATHER_FETCH_START'作爲其type屬性值的只有可能的選擇。根據單獨的類型,任何操作可能會有任何值的類型。我們唯一能確定的是它是一個字符串。

解決方案是定義您的行爲變體以具有更具體的類型,其中包含其合法值。

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',流量可某些實際類型爲FetchWeatherStartAction。這是可能的,因爲它已經知道actionWeatherActionWeatherAction是一個枚舉,只有這三個可能的值。

這有點不幸,你必須重複字符串文字,而不是引用常量。我知道人們對此感到不安,但在這種情況下,我會認爲所有魔術常量被認爲是不好的做法的原因都由Flow的類型檢查來處理。在Javascript中,使用語法標識符訪問字段在語義上與通過字符串名稱訪問它沒有區別。

+0

這是有道理的,我試圖將該常量分配爲「類型」的類型,但確實無法正常工作。我會考慮用字符串替換常量。感謝您的解釋。 – CasperDeseyne