The time to show off my skills is here! For my final project for Flatiron I built an application that mimics sites like Etsy, eBay and (specifically) Reverb. It is a website called "Sell It!" that allows users to sign up and list their audio gear or instruments to sell to other users. As one of our learning goals for this project, we needed to implement Redux in our application.
Redux was a blast to utilize. It made state data so much easier to manage. At first the setup was a little confusing and sometimes updating data can get a little twisted, especially if you're using any nested data in your site, but it's worth figuring it out and learning a new thing that streamlines prop sharing.
Redux gives the developer of an app a single, centralized place where our state data is contained. This eliminates the need for prop sharing through a tree. It also requires a specific pattern to be followed in order to update state.
There are a handful of new terms that you need to learn when utilizing Redux. Here's a quick rundown of the different functions:
Store: The store is where the current Redux application state lives. When we set up our application, we create the store in our index.js file so that immediately upon loading, the user has access to current data. This is also where we can implement other Redux middleware that I will not be covering in this blog post.
const store = createStore(rootReducer, composeWithDevTools(applyMiddleware(thunk)))
Action: An action is a JavaScript object that has a "type" field. An action is an event that describes what event is happening in the application. For example, addItem would be a good action name to describe adding an item to your store.
export const addItem = item => {
return (dispatch) => {
dispatch({ type: "CREATE_ITEM", payload: item })
}
}
Dispatch: The Redux store has a method called dispatch. The only way to update state is to call dispatch() and pass in an action object. Here you can see a short function that is triggered by an event (pushing a delete button) that dispatches the deleteItem action with an id being passed to the action.
function handleDeleteListing (e) {
dispatch(deleteItem(e.target.id))
}
Reducers: A reducer is a function that
- Receives the current state and an action object
- Decides how to update state if necessary
- Returns the new state A reducer functions similarly to an event listener based on the action it receives.
Above I showed the addItem action, that dispatches an object. In the object is a "type" key whole value is "CREATE_ITEM". When dispatched, the reducer looks for the matching action type and updates and returns state based on the data being sent in the payload value (in this case, the new item).
const itemsReducer = (state=initialState, action) => {
switch(action.type) {
case "CREATE_ITEM":
return {
...state,
items: [...state.items, action.payload]
};
default:
return state;
}
}
Selector: The selector function is used in any component where you need to access the store. When it's time to access the store to display the items, we define our variable and then "select" the data from the store that we want to access. Below I've shown two different ways of defining what data we want to access from which reducer (store.items or store.sessions).
const items = useSelector(store => store.items)
const { loggedIn, currentUser } = useSelector(store => store.sessions);
The way that data flows one way through Redux is brilliant.
First, state describes the condition of the app at that point in time, and UI is rendered based on that state.
Next, when an event occurs in the app, an action is dispatched.
The store looks through the reducers to find the correct action type and updates state based on the action and the action's payload.
Then, the store tells the UI that there has been an update to the state, triggering a re-render based on the new state.
It's been a really great tool to use and I can't wait to build another app that uses Redux!
Top comments (0)