# React&Redux: Lesson2 UI + Redux ###### tags: `Recat2` # Introduction {%youtube i2pSr-MlCPU%} # UI {%youtube 8IkNVrCqtvo%} [Here's the commit with the changes made in this video.](https://github.com/udacity/reactnd-redux-todos-goals/commit/3cb66af8ea36d4be3e80037ad76cef0ed58d24c8) ## What We're Going to Build Now that we have an `index.html` file and all of the JavaScript code has been transferred over to script tags, let's start adding in a User Interface. Since our project has two pieces of state, we'll need two areas: 1. Todo list area 2. Goals area ![](https://i.imgur.com/I5QsDm0.png) So this is what we're going for. It's not the best looking website ever created, but this isn't a course on CSS ;-). If you want to make it stunningly beautiful, feel free to add some CSS to your project 👍🏼 We already have the Redux portion of our application working, but so far, we've just been manually running snippets of code to interact with the Redux Store. Let's create the UI above so that we can interact with the store using the browser. {%youtube 0M2gm4-IbGs%} [Here's the commit with the changes made in this video.](https://github.com/udacity/reactnd-redux-todos-goals/commit/c800637efb41fee3f4ea2a9392eb7a3025aac69f) ## Summary In this section, we added some minimal UI to our application. The actually state of our app hasn't changed at all, though. In the next section, we'll hook up our shiny new UI to our state so that entering content via the UI will update the application's state. # UI + State {%youtube b9HpVHhDvL4%} [Here's the commit with the changes made in this video.](https://github.com/udacity/reactnd-redux-todos-goals/commit/707da3250f13adfef00fdbf032a563135cdf939a) The changes we just added made it so whenever the Todo input field is submitted, it will add a Todo item to the state...and whenever the Goal input field is submitted, it will add a new Goal item to the state. Let's break this down into the steps that happen. First, we need to listen for when the buttons are clicked; we did this with the plain DOM `.addEventListener()` method: ```javascript document.getElementById('todoBtn').addEventListener('click', addTodo) document.getElementById('goalBtn').addEventListener('click', addGoal) ``` Pressing the `#todoBtn` will call `addTodo` which will add the new item to the state: ```javascript function addTodo () { const input = document.getElementById('todo') const name = input.value input.value = '' store.dispatch(addTodoAction({ name, complete: false, id: generateId() })); } ``` This method will extract the information from the input field, reset the input field, and then dispatch an `addTodoAction` Action Creator with the text that the user typed into the input field. So we're using the UI to change the state of our store, but these changes are not reflecting the new state visually in the UI. Let's do that, now. ![](https://i.imgur.com/Mgh0X9C.png) > If you need to brush up on these skills, check out our course [JavaScript and the DOM](https://www.udacity.com/course/javascript-and-the-dom--ud117). {%youtube p3PtYdpqSO0%} {%youtube pJ7wu1rU680%} [Here's the commit with the changes made in this video.](https://github.com/udacity/reactnd-redux-todos-goals/commit/4219bd4cc8649f9fa1db65b57eb332150ec10c3f) {%youtube aFYwjb2RSbE%} [Here's the commit with the changes made in this video.](https://github.com/udacity/reactnd-redux-todos-goals/commit/8b9fcbfa43d2fa8927e59fd2d0e61d6d0bb5737d) ## Summary In this section, we connected our functioning state application with a front-end UI. We added some form fields and buttons to our UI that can be used to add new Todo items and Goal items to the state. Updating the state will also cause the entire application to re-render so that the visual representation of the application matches that of the info stored in the state object. Now, we wrote all of this code ourselves. In the next section, we'll convert from using our custom library to using Redux. # This is Redux {%youtub 06YeYJkrGaw%} We're going to transition away from our custom code to using the actual Redux library. While we're working on this simple project, we'll be linkin to the hosted version of the Redux library. In the following video, we'll use this code to link to redux: ```htmlembedded <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.7.2/redux.min.js"></script> ``` {%youtube Sg482OZsFzM%} [Here's the commit with the changes made in this video.](https://github.com/udacity/reactnd-redux-todos-goals/commit/d4975c2245e6d590f637e0873d30ae8d6454e372) Reducer composition sounds intimidating, but it's simpler than you might think. The idea is that you can create a reducer to manage not only each section of your Redux store, but also any nested data as well. Let's say we were dealing with a state tree like had this structure ```json { users: {}, setting: {}, tweets: { btyxlj: { id: 'btyxlj', text: 'What is a jQuery?', author: { name: 'Tyler McGinnis', id: 'tylermcginnis', avatar: 'twt.com/tm.png' } } } } ``` We have three main properties on our state tree: users, settings, and tweets. Naturally, we'd create an individual reducer for both of those and then create a single root reducer using Redux's `combineReducers` method. ```javascript const reducer = combineReducers({ users, settings, tweets }) ``` `combineReducers`, under the hood, is our first look at reducer composition. `combineReducers` is responsible for invoking all the other reducers, passing them the portion of their state that they care about. We're making one root reducer, by composing a bunch of other reducers together. With that in mind, let's take a closer look at our tweets reducer and how we can leverage reducer composition again to make it more compartmentalized. Specifically, let's look how a user might change their avatar with the way our store is currently structured. Here's the skeleton with what we'll start out with - ```javascript function tweets (state = {}, action) { switch(action.type){ case ADD_TWEET : ... case REMOVE_TWEET : ... case UPDATE_AVATAR : ??? } } ``` What we're interested in is that last one, `UPDATE_AVATAR`. This one is interesting because we have some nested data - and remember, reducers have to be pure and can't mutate any state. Here's one approach. ```javascript function tweets (state = {}, action) { switch(action.type){ case ADD_TWEET : ... case REMOVE_TWEET : ... case UPDATE_AVATAR : return { ...state, [action.tweetId]: { ...state[action.tweetId], author: { ...state[action.tweetId].author, avatar: action.newAvatar } } } } } ``` That's a lot of spread operators. The reason for that is because, for every layer, we're wanting to spread all the properties of that layer on the new objects we're creating (because, immutability). What if, just like we separated our tweets, users, and settings reducers by passing them the slice of the state tree they care about, what if we do the same thing for our tweets reducer and its nested data. Doing that, the code above would be transformed to look like this ```javascript function author (state, action) { switch (action.type) { case : UPDATE_AVATAR return { ...state, avatar: action.newAvatar } default : state } } function tweet (state, action) { switch (action.type) { case ADD_TWEET : ... case REMOVE_TWEET : ... case : UPDATE_AVATAR return { ...state, author: author(state.author, action) } default : state } } function tweets (state = {}, action) { switch(action.type){ case ADD_TWEET : ... case REMOVE_TWEET : ... case UPDATE_AVATAR : return { ...state, [action.tweetId]: tweet(state[action.tweetId], action) } default : state } } ``` All we've done is separated out each layer of our nested tweets data into their own reducers. Then, just like we did with our root reducer, we're passing those reducers the slice of the state they care about. ![](https://i.imgur.com/dcnDqYw.png) ## Summary In this section, we replaced the code we wrote in the previous lesson with the actual Redux library code. We saw that swapping out our code with Redux's code didn't change anything with how our application functions or how our app-specific code works. Redux is just a predictable state container. What's key to understand is that you've already learned 90% of Redux! Everything else from here on out will be handling specific use cases (combining Redux with a React application, how to work with asynchronous data modification, etc.). So we'll be adding more concepts on top of what you know now, so if you feel comfortable with your understanding of Redux, then keep going. If you're a bit hazy on how a specific part works, I definitely recommend you get they hazy bits nailed down now before proceeding on to more complicated content. Feel free to return to the first lesson to review specific Redux functionalities to iron out any confusing parts before moving on. # Summary {%youtube 45ileyqFeGw%} ## Lesson Challenge #1 Read these articles: The what and why of Redux and Leveling Up with React: Redux. Answer the following questions (in your own words) and share your answers with your classmates: 1) What are the advantages of using Redux? 2) Describe the 3 principles Redux follows.