Может кто-нибудь объяснить функцию редуктора этого заголовка функции редуктора?

Для некоторых этот вопрос может показаться тривиальным, но я уже некоторое время изучаю реакцию, редукцию и javascript. Единственная недостающая часть — машинописный текст. Я хочу понять функцию редуктора в этом фрагменте кода. В частности, заголовок функции.

Этот код взят непосредственно из примера в шаблоне кода Visual Studio 2019 React Redux для ядра ASP.net 3.0. В частности, файл WeatherForecast.ts в папке src/store. Я не смог найти много документации об этом примере, так как он довольно новый. Насколько я понимаю, он использует избыточный преобразователь с шаблоном цепочки функций. Что, по-моему, меня смущает, так это приведение типов с машинописным текстом. Я довольно хорошо понимаю остальную часть шаблона, но я думаю, что это машинописный текст, который сбивает меня с толку в отношении редуктора.

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;
};

Ошибок нет. Мне просто нужно понять семантику этих заголовков функций.


person Ali TK    schedule 07.07.2019    source источник


Ответы (1)


Это обычная структура действия async для редуктора, но с использованием машинописного текста.

В основном вы определяете типы данных как interfaces вверху, это просто объекты, определяющие, какие данные вы ожидаете передать.

Затем у вас есть действие и редуктор. Их реализация точно такая же, как и у обычного react-redux. Однако вы реализуете действие async (выполняете асинхронный вызов с использованием fetch), поэтому вам также необходимо использовать redux-thunk и его тип из машинописного текста, AppThunkAction.

Поэтому вам необходимо указать, какие «элементы» (тип данных) должна передавать каждая функция.

Если вам нужен определенный тип данных (сложный тип), удобно создать для него interface. В противном случае вы можете повторить этот сложный тип после столбцов (:) каждого объекта, которому хотите его присвоить, но это не рекомендуется.

Например, если я ожидаю объект от вызова API с id, name, hobbies и timestamp, интерфейс для этого сложного типа будет таким:

export interface dataFromAPICall {
    id: number;
    name: string;
    hobbies?: string[];
    timestamp: number;
}

В этом случае хобби является необязательным (?), и он ожидает и массив строк ['football', 'sky', 'bodyboard surfing'].

В случае сложных типов в популярных библиотеках обычно эти типы уже определены, например, AppThunkAction в редукции или ReactNode в React.

Надеюсь это поможет!

person Alberto Ruiz    schedule 07.07.2019
comment
так что, насколько я понимаю, эта строка: export const reducer: Reducer<WeatherForecastsState> = (state: WeatherForecastsState | undefined, incomingAction: Action): WeatherForecastsState => { означает, что мы определяем константную переменную, называемую редуктором, которая имеет тип Reducer‹WeatherforecastsState›, который равен экземпляру функции редуктора, которая имеет тип WeatherForecastsState. Хорошо, не могли бы вы указать мне на некоторые ресурсы машинописи, о которых я могу прочитать и изучить этот тип промежуточной нотации? - person Ali TK; 07.07.2019