This is the "Redux manufacturing" project, which simulates a warehouse that accepts orders, prepares them for delivery, and ships them. It's built with React and Redux.
The project starts with an existing codebase built without Redux. We'll integrate Redux and react-redux
, move the component-level functions into reducers, and define actions to be dispatched from the component to make these state changes happen.
A number of functions are defined in the top-level component, App.js
. These functions are passed in as props to various components, and are called to update the App
component's state.
We need to move each of these functions into the Redux reducer function, ensure that they are pure functions, and define the appropriate actions (and constants) to be able to dispatch those actions from components.
- A function in a top-level component that updates state should be moved into the reducer. Look at what state modifications it makes (what does it change in
this.setState
), and ensure those same keys (orders
,packaged
) are defined in the Redux state object.
generateOrder() {
// $DOSTUFF
this.setState({
});
}
In Redux:
function appReducer(state, action) {
switch (action.type) {
case GENERATE_ORDER:
// $DOSTUFF
}
}
Adding an action constant, and the action creator for dispatching that action should be done in actions.js
:
// actions.js
export const GENERATE_ORDER = 'GENERATE_ORDER'
export generateOrder = () => { return {
type: GENERATE_ORDER
}}
In the component:
// App.js
import { generateOrder } from './actions';
class App extends React.Component {
render() {
return (
<div>
<button onClick={this.props.generateOrder}>
Generate order
</button>
</div>
)
}
}
Generally, if a component was relying on this.state.<something>
, moving that piece of data into Redux application state means that it will become available at this.props.<something>
, if passed into the container component.
If an action needs to do some kind of logic (checking an existing value in state, or picking between actions to dispatch), or if it needs to dispatch more than one action, it should be a "thunked" action:
const thunkedAction = () => {
return dispatch => {
dispatch({ type: 'AN_ACTION' })
}
}
Actions dispatched inside of a thunked action can be action creators:
const anAction = () => { return { type: AN_ACTION { {
const thunkedAction = () => {
return dispatch => {
dispatch(anAction())
}
}
In general, you should be able to move the pieces of functionality in the component into the reducer, and update the behavior accordingly. For instance, instead of referring to this.state
, we should have access to the variable state
from inside the reducer.
Otherwise, that might be my bad. If the component itself is unclear (what does "packaging an order" mean?), feel free to ask me and I'll do my best to explain.
- Passing props
<MyComponent propName={propValue} />
// In MyComponent, access prop as...
this.props.propName
- Reducer functions
function myReducer(state, action) {
switch (action.type) {
case ACTION_CONSTANT:
return $newversionofstate;
}
}
- Exporting action constants
export const ADD_ITEM = 'ADD_ITEM'
- Action creators
export const addItem = () => { return {
type: ADD_ITEM
}}