- Define action types
- Create action creator functions
- Implement a reducer
- Configure the project reducer and state
-
Create the directory
src\projects\state
. -
Create the file
src\projects\state\projectTypes.js
. -
Define the project
actions types
.//action types export const LOAD_PROJECTS_REQUEST = 'LOAD_PROJECTS_REQUEST'; export const LOAD_PROJECTS_SUCCESS = 'LOAD_PROJECTS_SUCCESS'; export const LOAD_PROJECTS_FAILURE = 'LOAD_PROJECTS_FAILURE'; export const SAVE_PROJECT_REQUEST = 'SAVE_PROJECT_REQUEST'; export const SAVE_PROJECT_SUCCESS = 'SAVE_PROJECT_SUCCESS'; export const SAVE_PROJECT_FAILURE = 'SAVE_PROJECT_FAILURE'; export const DELETE_PROJECT_REQUEST = 'DELETE_PROJECT_REQUEST'; export const DELETE_PROJECT_SUCCESS = 'DELETE_PROJECT_SUCCESS'; export const DELETE_PROJECT_FAILURE = 'DELETE_PROJECT_FAILURE';
-
Create the file
src\projects\state\projectActions.js
. -
Define your action creator functions and return a
ThunkAction
(function
) instead of just anAction
(object
) to handle the asyncronous nature of the HTTP calls happening.import { projectAPI } from '../projectAPI'; import { LOAD_PROJECTS_REQUEST, LOAD_PROJECTS_SUCCESS, LOAD_PROJECTS_FAILURE, SAVE_PROJECT_REQUEST, SAVE_PROJECT_SUCCESS, SAVE_PROJECT_FAILURE, } from './projectTypes'; //action creators export function loadProjects(page) { return (dispatch) => { dispatch({ type: LOAD_PROJECTS_REQUEST }); return projectAPI .get(page) .then((data) => { dispatch({ type: LOAD_PROJECTS_SUCCESS, payload: { projects: data, page }, }); }) .catch((error) => { dispatch({ type: LOAD_PROJECTS_FAILURE, payload: error }); }); }; } export function saveProject(project) { return (dispatch) => { dispatch({ type: SAVE_PROJECT_REQUEST }); return projectAPI .put(project) .then((data) => { dispatch({ type: SAVE_PROJECT_SUCCESS, payload: data }); }) .catch((error) => { dispatch({ type: SAVE_PROJECT_FAILURE, payload: error }); }); }; }
- Create the file
src\projects\state\projectReducer.js
. - Define your reducer function.
src\projects\state\projectReducer.js
import { Project } from '../Project';
import {
LOAD_PROJECTS_REQUEST,
LOAD_PROJECTS_SUCCESS,
LOAD_PROJECTS_FAILURE,
DELETE_PROJECT_REQUEST,
DELETE_PROJECT_SUCCESS,
DELETE_PROJECT_FAILURE,
SAVE_PROJECT_REQUEST,
SAVE_PROJECT_SUCCESS,
SAVE_PROJECT_FAILURE,
} from './projectTypes';
export const initialProjectState = {
projects: [],
loading: false,
error: undefined,
page: 1,
};
export function projectReducer(state = initialProjectState, action) {
switch (action.type) {
case LOAD_PROJECTS_REQUEST:
return { ...state, loading: true, error: '' };
case LOAD_PROJECTS_SUCCESS:
let projects;
const { page } = action.payload;
if (page === 1) {
projects = action.payload.projects;
} else {
projects = [...state.projects, ...action.payload.projects];
}
return {
...state,
loading: false,
page,
projects,
error: '',
};
case LOAD_PROJECTS_FAILURE:
return { ...state, loading: false, error: action.payload.message };
case SAVE_PROJECT_REQUEST:
return { ...state };
case SAVE_PROJECT_SUCCESS:
let updatedProject = new Project(action.payload);
if (updatedProject.isNew()) {
return {
...state,
projects: [...state.projects, updatedProject],
};
} else {
return {
...state,
projects: state.projects.map((project) => {
return project.id === action.payload.id
? Object.assign(new Project(), project, updatedProject)
: project;
}),
};
}
case SAVE_PROJECT_FAILURE:
return { ...state, error: action.payload.message };
case DELETE_PROJECT_REQUEST:
return { ...state };
case DELETE_PROJECT_SUCCESS:
return {
...state,
projects: state.projects.filter(
(project) => project.id !== action.payload.id
),
};
case DELETE_PROJECT_FAILURE:
return { ...state, error: action.payload.message };
default:
return state;
}
}
- update state.js
-
Open the file
src\state.js
. -
Configure the
projectReducer
andProjectState
.import { createStore, applyMiddleware } from 'redux'; import ReduxThunk from 'redux-thunk'; import { composeWithDevTools } from 'redux-devtools-extension'; import { combineReducers } from 'redux'; + import { initialProjectState } from './projects/state/projectReducer'; + import { projectReducer } from './projects/state/projectReducer'; const reducer = combineReducers({ + projectState: projectReducer }); ... export const initialAppState = { + projectState: initialProjectState }; export const store = configureStore(initialAppState);
-
Verify the application compiles.
In the next lab we will connect our Redux code to our React application.