有人可以解释一下这个 reducer 函数头的 reducer 函数吗?
Can someone please explain the reducer function of this reducer function header?
这个问题对某些人来说可能看起来微不足道,但我已经研究了 React、redux 和 javascript 一段时间了。唯一缺少的部分是打字稿。我想了解这段代码中的reducer功能。特别是函数头。
此代码直接取自 visual studio code 2019 react redux template for ASP.net core 3.0 中的示例。特别是 src/store 文件夹中的 WeatherForecast.ts 文件。我找不到很多关于这个例子的文档,因为它很新。据我了解,它使用带有函数链接模式的 redux thunk。我认为让我感到困惑的是打字稿的类型转换。我非常了解模板的其余部分,但我认为是 typescript 让我对 reducer 望而却步。
import { Action, Reducer } from 'redux';
import { AppThunkAction } from './';
// -----------------
// STATE - This defines the type of data maintained in the Redux store.
export interface WeatherForecastsState {
isLoading: boolean;
startDateIndex?: number;
forecasts: WeatherForecast[];
}
export interface WeatherForecast {
dateFormatted: string;
temperatureC: number;
temperatureF: number;
summary: string;
}
// -----------------
// ACTIONS - These are serializable (hence replayable) descriptions of state transitions.
// They do not themselves have any side-effects; they just describe something that is going to happen.
interface RequestWeatherForecastsAction {
type: 'REQUEST_WEATHER_FORECASTS';
startDateIndex: number;
}
interface ReceiveWeatherForecastsAction {
type: 'RECEIVE_WEATHER_FORECASTS';
startDateIndex: number;
forecasts: WeatherForecast[];
}
// Declare a 'discriminated union' type. This guarantees that all references to 'type' properties contain one of the
// declared type strings (and not any other arbitrary string).
type KnownAction = RequestWeatherForecastsAction | ReceiveWeatherForecastsAction;
// ----------------
// ACTION CREATORS - These are functions exposed to UI components that will trigger a state transition.
// They don't directly mutate state, but they can have external side-effects (such as loading data).
export const actionCreators = {
requestWeatherForecasts: (startDateIndex: number): AppThunkAction<KnownAction> => (dispatch, getState) => {
// Only load data if it's something we don't already have (and are not already loading)
const appState = getState();
if (appState && appState.weatherForecasts && startDateIndex !== appState.weatherForecasts.startDateIndex) {
fetch(`api/SampleData/WeatherForecasts?startDateIndex=${startDateIndex}`)
.then(response => response.json() as Promise<WeatherForecast[]>)
.then(data => {
dispatch({ type: 'RECEIVE_WEATHER_FORECASTS', startDateIndex: startDateIndex, forecasts: data });
});
dispatch({ type: 'REQUEST_WEATHER_FORECASTS', startDateIndex: startDateIndex });
}
}
};
// ----------------
// REDUCER - For a given state and action, returns the new state. To support time travel, this must not mutate the old state.
const unloadedState: WeatherForecastsState = { forecasts: [], isLoading: false };
export const reducer: Reducer<WeatherForecastsState> = (state: WeatherForecastsState | undefined, incomingAction: Action): WeatherForecastsState => {
if (state === undefined) {
return unloadedState;
}
const action = incomingAction as KnownAction;
switch (action.type) {
case 'REQUEST_WEATHER_FORECASTS':
return {
startDateIndex: action.startDateIndex,
forecasts: state.forecasts,
isLoading: true
};
case 'RECEIVE_WEATHER_FORECASTS':
// Only accept the incoming data if it matches the most recent request. This ensures we correctly
// handle out-of-order responses.
if (action.startDateIndex === state.startDateIndex) {
return {
startDateIndex: action.startDateIndex,
forecasts: action.forecasts,
isLoading: false
};
}
break;
}
return state;
};
没有错误。我只需要了解这些函数头的语义即可。
这是对 reducer 的 async
操作的常用结构,但使用的是打字稿。
基本上,您将数据类型定义为顶部的 interfaces
,这些只是定义您希望传递的数据类型的对象。
然后,你就有了 action 和 reducer。
这些的实现与常规 react-redux 完全相同。但是,您正在实施 async
操作(使用 fetch
进行异步调用),因此您还需要使用 redux-thunk
及其来自打字稿的类型 AppThunkAction
.
因此,您需要指定 'thing' 每个函数期望传递的(数据类型)。
如果您需要特定的数据类型(复杂类型),为它创建一个 interface
会很方便。否则,您可以在要分配给它的每个对象的列 (:
) 之后重复此复杂类型,但不建议这样做。
例如,如果我希望通过 id
、name
、hobbies
和 timestamp
的 API 调用得到一个对象,一个接口对于该复杂类型将是:
export interface dataFromAPICall {
id: number;
name: string;
hobbies?: string[];
timestamp: number;
}
在这种情况下,hobbies 是可选的 (?
),它需要字符串数组 ['football', 'sky', 'bodyboard surfing']
。
对于流行库中的复杂类型,通常已经定义了这些类型,例如 redux 中的 AppThunkAction
或 React 中的 ReactNode
。
希望对您有所帮助!
这个问题对某些人来说可能看起来微不足道,但我已经研究了 React、redux 和 javascript 一段时间了。唯一缺少的部分是打字稿。我想了解这段代码中的reducer功能。特别是函数头。
此代码直接取自 visual studio code 2019 react redux template for ASP.net core 3.0 中的示例。特别是 src/store 文件夹中的 WeatherForecast.ts 文件。我找不到很多关于这个例子的文档,因为它很新。据我了解,它使用带有函数链接模式的 redux thunk。我认为让我感到困惑的是打字稿的类型转换。我非常了解模板的其余部分,但我认为是 typescript 让我对 reducer 望而却步。
import { Action, Reducer } from 'redux';
import { AppThunkAction } from './';
// -----------------
// STATE - This defines the type of data maintained in the Redux store.
export interface WeatherForecastsState {
isLoading: boolean;
startDateIndex?: number;
forecasts: WeatherForecast[];
}
export interface WeatherForecast {
dateFormatted: string;
temperatureC: number;
temperatureF: number;
summary: string;
}
// -----------------
// ACTIONS - These are serializable (hence replayable) descriptions of state transitions.
// They do not themselves have any side-effects; they just describe something that is going to happen.
interface RequestWeatherForecastsAction {
type: 'REQUEST_WEATHER_FORECASTS';
startDateIndex: number;
}
interface ReceiveWeatherForecastsAction {
type: 'RECEIVE_WEATHER_FORECASTS';
startDateIndex: number;
forecasts: WeatherForecast[];
}
// Declare a 'discriminated union' type. This guarantees that all references to 'type' properties contain one of the
// declared type strings (and not any other arbitrary string).
type KnownAction = RequestWeatherForecastsAction | ReceiveWeatherForecastsAction;
// ----------------
// ACTION CREATORS - These are functions exposed to UI components that will trigger a state transition.
// They don't directly mutate state, but they can have external side-effects (such as loading data).
export const actionCreators = {
requestWeatherForecasts: (startDateIndex: number): AppThunkAction<KnownAction> => (dispatch, getState) => {
// Only load data if it's something we don't already have (and are not already loading)
const appState = getState();
if (appState && appState.weatherForecasts && startDateIndex !== appState.weatherForecasts.startDateIndex) {
fetch(`api/SampleData/WeatherForecasts?startDateIndex=${startDateIndex}`)
.then(response => response.json() as Promise<WeatherForecast[]>)
.then(data => {
dispatch({ type: 'RECEIVE_WEATHER_FORECASTS', startDateIndex: startDateIndex, forecasts: data });
});
dispatch({ type: 'REQUEST_WEATHER_FORECASTS', startDateIndex: startDateIndex });
}
}
};
// ----------------
// REDUCER - For a given state and action, returns the new state. To support time travel, this must not mutate the old state.
const unloadedState: WeatherForecastsState = { forecasts: [], isLoading: false };
export const reducer: Reducer<WeatherForecastsState> = (state: WeatherForecastsState | undefined, incomingAction: Action): WeatherForecastsState => {
if (state === undefined) {
return unloadedState;
}
const action = incomingAction as KnownAction;
switch (action.type) {
case 'REQUEST_WEATHER_FORECASTS':
return {
startDateIndex: action.startDateIndex,
forecasts: state.forecasts,
isLoading: true
};
case 'RECEIVE_WEATHER_FORECASTS':
// Only accept the incoming data if it matches the most recent request. This ensures we correctly
// handle out-of-order responses.
if (action.startDateIndex === state.startDateIndex) {
return {
startDateIndex: action.startDateIndex,
forecasts: action.forecasts,
isLoading: false
};
}
break;
}
return state;
};
没有错误。我只需要了解这些函数头的语义即可。
这是对 reducer 的 async
操作的常用结构,但使用的是打字稿。
基本上,您将数据类型定义为顶部的 interfaces
,这些只是定义您希望传递的数据类型的对象。
然后,你就有了 action 和 reducer。
这些的实现与常规 react-redux 完全相同。但是,您正在实施 async
操作(使用 fetch
进行异步调用),因此您还需要使用 redux-thunk
及其来自打字稿的类型 AppThunkAction
.
因此,您需要指定 'thing' 每个函数期望传递的(数据类型)。
如果您需要特定的数据类型(复杂类型),为它创建一个 interface
会很方便。否则,您可以在要分配给它的每个对象的列 (:
) 之后重复此复杂类型,但不建议这样做。
例如,如果我希望通过 id
、name
、hobbies
和 timestamp
的 API 调用得到一个对象,一个接口对于该复杂类型将是:
export interface dataFromAPICall {
id: number;
name: string;
hobbies?: string[];
timestamp: number;
}
在这种情况下,hobbies 是可选的 (?
),它需要字符串数组 ['football', 'sky', 'bodyboard surfing']
。
对于流行库中的复杂类型,通常已经定义了这些类型,例如 redux 中的 AppThunkAction
或 React 中的 ReactNode
。
希望对您有所帮助!