Skip to content

Generate Action

Generate Action

Location: client/actions/

Actions are the place to coding sagas and reduxsuaces.

Files Created

The Generator of Action will the following files:

  • index.ts - this export all reducers, selectors, and sagas. and also create all the watchers.
  • sagas.ts - here all the sagas functions.
  • redux.ts - here all the reducers/selectors functions.
  • interface.ts - here all the interfaces define.
  • manager.ts - utils functions to help mapping, configurations etc ... that needed for sagas and reducers.

Create Action by cli

$ gulp createAction --name myAction

sagas.ts

import { createDraft, Draft } from 'immer';
import { createReducerCase } from '@base/features/base-decorator';
import { createReducer, createActions } from 'reduxsauce';
import { ApplicationState } from 'actions';
import {
    TodoState, TypesNames, ActionCreator, SetExampleAction
} from './interface';

/* ------------- Types and Action Creators ------------- */

const { Creators } = createActions<TypesNames, ActionCreator>({
    mySaga: ['someData'], // handle by saga
    setExample: ['exampleData']
});

export const TodoTypes = TypesNames;
export const TodoActions = Creators;

/* ------------- Initial State ------------- */

const INITIAL_STATE = createDraft<TodoState>({
    exampleData: 'Initial Data Example'
});

/* ------------- Selectors ------------- */

export const todoSelector = {
    getExampleData: (state: ApplicationState) => state.todo?.exampleData
};

/* ------------- Reducers ------------- */

const setExampleReducer = (draft: Draft<TodoState>, action: SetExampleAction) => {
    const { exampleData } = action;
    draft.exampleData = exampleData;
};

/* ------------- Hookup Reducers To Types ------------- */

export const reducer = createReducer<any, any>(INITIAL_STATE, {
    [TypesNames.SET_EXAMPLE]: createReducerCase(setExampleReducer)
});

index.ts

import { all, fork, takeLatest } from 'redux-saga/effects';
import { createSaga } from '@base/features/base-decorator';
import * as Sagas from 'actions/todo/sagas';
import { TodoTypes } from 'actions/todo';

/* ------------- Export Redux ------------- */
export * from 'actions/todo/redux';

/* ------------- Export Sagas ------------- */
function* watchMySaga() {
    yield takeLatest(TodoTypes.MY_SAGA, createSaga(Sagas.mySaga));
}

export function* todoSaga() {
    yield all([
        fork(watchMySaga)
    ]);
}

interface.ts

import { Action } from 'redux';

/* ------------- Define Actions and State ------------- */
export interface TodoState {
    exampleData: string;
}

export enum TypesNames {
    SET_EXAMPLE = 'SET_EXAMPLE',
    MY_SAGA = 'MY_SAGA'
}

export declare function SetExampleFunction(exampleData: string): SetExampleAction;
export declare function MySagaFunction(someData: string): MySagaAction;

export interface ActionCreator {
    setExample: typeof SetExampleFunction;
    mySaga: typeof MySagaFunction;
}

export interface SetExampleAction extends Action<TypesNames.SET_EXAMPLE> {
    exampleData: string;
}

export interface MySagaAction extends Action<TypesNames.MY_SAGA> {
    someData: string;
}

/* ------------- Define Any Interfaces ------------- */
export interface ResponseExample {
    name: string;
}

manager.ts

// Here you right all the "sdk" ( managers, utils etc .. )
// actually here is a function that are not saga and should return simple values without dispatch
// for example function that get a and b and return a + b

Redux Sagas

For more information, read on https://github.com/redux-saga/redux-saga
What is takeLatest?

(alias) takeLatest<any, any>(pattern: Pattern<any>, worker: HelperFunc1<any, any>, arg1: any): ForkEffect (+5 overloads)
import takeLatest

Alternatively you may use takeLatest.

Does not allow concurrent fetches of user. If "SOME_ACTION" gets dispatched while a fetch is already pending, that pending fetch is cancelled and only the latest one will be run.