Redux in a nutshell is a collection of all the data that describes the application, while react represents the view which translates the apps data into something a user can interact with. Redux is totally seperate from React, in fact we use a library called react-redux to bridge them together. We centralize all of the data in the application into one object (application state).
- React
- Redux
- react-redux (module)
- redux (module)
- ACTIONS
- Action Cycle
- Some event is triggered in the browser: either an user event (button click) or browser event (page load) etc..
- Calls an Action Creactor
- An action creator is just a function that returns an action which is an object, that has a mandatory type property that describes the purpose of the action.
- The returned action is automatically sent to all reducers in the application to be interpreted
- The reducer has a switch statement that switches on the action type.
- The default case is to simply return the current state
- Once all reducers process the action the newly assembled state is pumped back into the containers, then the browser is re-rendered with new data
- Action Cycle
// IN THE CONTAINER THIS FUNCTION IS PASSED A BOOK
export function selectBook(book){
return {
type: 'BOOK_SELECTED', // DESCRIBES THE TYPE OF EVENT/ACTION
payload: book // DATA
};
}
- REDUCERS
- All reducers get two arguments (state, action)
- State argument is not application state, only the state this reducer is responsible for
- The applications state is formed by the reducers and changes depending on the type of action
- Reducers are only called when an action takes place
- Reducers are simply functions that return a peice of the application state
- When the application first loads Redux will send an action to all reducers
- At this point, the reducer will return an undefined value for state, which is why we default the state to null. You should never return an undefined state.
- Also, our components that rely on this data will receive null values for state.
- NEVER mutate state
- All reducers get two arguments (state, action)
// DEFAULT STATE TO NULL TO PREVENT RETURNING AN UNDEFINED VALUE
export default function(state = null, action){
switch (action.type) {
case 'BOOK_SELECTED':
return action.payload;
}
// IF WE DON'T CARE ABOUT THE ACTION, JUST RETURN STATE
return state;
}
- ROOT REDUCER
- Uses combineReducers which is a method from redux to form an object that maps our state to the containers
import { combineReducers } from 'redux';
// IMPORT REDUCERS
import BooksReducer from './reducer_books';
import ActiveBookReducer from './reducer_active_book';
// APPLICATION STATE CENTRALIZED INTO ONE OBJECT THAT GETS CALLED BY OUR CONTAINERS
const rootReducer = combineReducers({
books: BooksReducer,
activeBook: ActiveBookReducer
});
export default rootReducer;
- Import these two into the container
// glue between React and Redux
import { connect } from 'react-redux';
// use this to make sure the action generated by the Action Creator flows through the reducers
import { bindActionCreators } from 'redux';
-
A container is a react component that has a direct connection to our state managed by redux
- Also called "smart components"
- The most parent component that cares about a particular peice of state
- Only the container component is connected to redux
- A component that is aware of the state thats contained by Redux
-
Two manadatory methods inside of containers:
// takes our application state as an argument
// this function is the glue between React and Redux
// whenever our application state changes, this container will instantly re-render
function mapStateToProps(state) {
// whatever gets returned will show up as props inside of the container
return {
// to reference this object we use "this.props.books", because "books" is the key we assigned
// "state.books" is a reference to the global state object formed by combineReducers()
books: state.books
};
}
// anything returned from this function will end up as props to the container
// now we can call this.props.selectBook for our (onClick example)
function mapDispatchToProps(dispatch){
// Whenever selectBook is called the result will be passed to all reducers
// dispatch is a function, the 2nd parameter that makes sure the result is received and sent to all the reducers
// selectBook is a function that returns an object
// the purpose of bindActionCreators and dispatch is to specifically take what gets returned from selectBook and make sure it flows through all reducers
return bindActionCreators({ selectBook }, dispatch);
}
- Lastly
// connect takes a function and a component and produces a container
// whenever the application state changes the object in mapStateToProps will be assigned as props to the component
export default connect(mapStateToProps, mapDispatchToProps)(BookList);