Check out our Angular Book Series.

Learning Redux - Saying Goodbye to Hello World - Part 3

This is the third part in a series on Redux, a state Management Framework used with single page application frameworks such as React and Angular. This article series looks at using Redux without another framework. Please read part 1, and Part 2 before reading this.

I write about Redux and Angular in the bonus book to the Angular 6 series.

This article will expand on the previous "hello world" sample to teach you how to say Goodbye.

Add a new state to the Reducer

With every hello comes a goodbye. We are going to create a button that will say goodbye to the user, and then clear out the helloUser value from the store. The purpose of this sample is to add more objects in the store.

First, let's start with the UI:


<button id="goodbyebtn">GoodBye</button><br/><br/>
GoodBye <span id="goodbyeValue"></span>

I added a Goodbye Button, and a span for the goodbyeValue. Back to the JavaScript, handle a click on the goodbyebtn:


document.getElementById('goodbyebtn')
.addEventListener('click', function (e) {
store.dispatch({ type: 'NAME_LEFT',
value : store.getState().helloUser})
})

This dispatches an action. The type is NAME_LEFT. The value is the current helloUser.

Let's go back to our reducer function and add some code to handle this new action:


case 'NAME_LEFT':
newState.goodbyeUser = action.value;
newState.helloUser = '';
break;

It is just another case statement in the switch. We set a new value on the state to goodbyeUser, and set the helloUser value to an empty string. When we set the default, near the beginning of the reducer() method, be sure to initialize the goodbyeUser state property:


if (typeof state === 'undefined') {
newState = {
helloUser : '',
goodbyeUser : ''
}
}

Now we need to create a function to render the code:


function renderGoodbye() {
document.getElementById('goodbyeValue').innerHTML =
store.getState().goodbyeUser.toString()
}

This just uses getElementByID() to get the span for the goodbyeValue. It sets the innerHTML to the stores goodbyeUser property. Make sure you subscribe: store.subscribe(renderGoodbye)

The code should be runnable now:

Enter your name and you'll "Hello Jeffry", just as with our original sample. Then click the GoodBye button, and you'll see the name populate after Goodbye and the name after Hello blank out. I did not add code to blank out the user input, but you should be able to do that easily if needed.

Play with a live sample here.

Learning Redux - Vanilla JavaScript Sample - Part 2

Redux is a state Management Framework that is primarily used with React, but can also be used with Angular. This article series looks at using Redux without another framework. Please read part 1 before reading this.

I write about Redux and Angular in the bonus book to the Angular 6 series.

This article will show you how to write your first Redux application. We're going to create a simple Hello World style sample.

Set up the Infrastructure

Create a new blank HTML Page. It'll look something like this:


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Redux Vanilla JS</title>
</head>
<body>
</code>
</body>
</html>

Import the Redux library:


<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.0/redux.min.js">
</script>

Instead of using NodeJS and Build Script tools, I'm just pulling it out from an Internet based CDN because it is the simplest way. Create the reducer:


<script>
function reducer(state, action) {
}
</script>

The reducer is the function that will run when actions are dispatched to the store. It takes in the current state and the action, then runs code to determine what the new state will be. A reducer should not have any side effects. That means it should not modify the existing state. The first step is to make a copy of the existing state:


var newState = Object.assign({}, state)

On first run of the application, no existing state will be defined, so we'll check for that and set some defaults:


if (typeof state === 'undefined') {
newState = {
helloUser : ''
}
}

The state of the application is just a JavaScript object. I included one property on that object, helloUser and defaulted it to an empty string. Once we start dispatching events, we'll revisit this function to handle those event types. Until then, just return the new state:


return newState;

That completes the reducer, for the moment.

Now, create the store:


var store = Redux.createStore(reducer);

This calls the createStore() value on the Redux library. The reducer() function is passed in. Notice we are saving the store as a local variable for future reference. Do not put this line of code inside the reduce.

Let's create our simple UI:


Enter Your Name: <input id="username"><br/><br/>
Hello <span id="helloValue"></span>

We're going to set this up so that when the user types in the input, the text will automatically update in the span. I've seen similar samples used to demonstrate how binding works in Angular.

Let's switch back to JavaScript and create a function to render the UI:


function renderHello() {
document.getElementById('helloValue').innerHTML =
store.getState().helloUser.toString()
}

The renderHello() function accepts no arguments. It uses the JavaScript document object and getElementByID() function to retrieve the helloValue span. Then it populates it with the helloUser string in the state. We retrieve the state from the store using the getState() functionality. Be sure to call the renderHello() function immediately to render the function in the default state:


renderHello()

Whenever the state changes, we want to run this renderHello() function. We do that with the subscribe() function on the Redux store:


store.subscribe(renderHello)

Now, when the state changes, the renderHello() function will be called, thus causing the UI to update.

Whenever the username input is modified, we want to dispatch an action to the store so that the reducer() function runs, which will return the modified state, and then run the renderHello() listener to modify the UI. This is the code:


document.getElementById('username').addEventListener('keyup', function (e) {
store.dispatch({ type: 'NAME_MODIFIED', value : e.target.value})
})

Without a framework, such as Angular, it is a bit complex to listen for events on elements, but we grab the username input with getElementByID() and then listen for the keyup event. We use store.dispatch() to send a NAME_MODIFIED action. By convention, the type of the action is a constant put in all caps, but here we are hard coding it a bit.

We need to modify the reducer() function to handle the NAME_MODIFIED action:


switch (action.type) {
case 'NAME_MODIFIED':
newState.helloUser = action.value
break;
default:
// do nothing
}

This code is after the undefined check, and before the return statement. It is a switch statement that checks for the action's type, and does actions based on that. At this stage in the application, we only have a single event, but we'll add one more as we iterate over this code.

You should be able to run the code now:

As you type your name the text will appear after the hello.

Play with this sample.

And don't forget to pick up the Angular 6 books from the Learn With series.

Learning Redux - Definitions - Part 1

Redux is a state Management Framework that is primarily used with React. There is an Angular port of it, ngrx. I wanted to learn a bit about Redux and write about it in the latest Bonus book for my Angular 6 series.

This is the first in a series of articles about Vanilla Redux. In this article we'll talk a bit about terminology used for Redux and how a Redux application should flow.

Understanding Redux Terminology

Many frameworks have their own terminology, so this section will explain some common terminology.

  • Actions: Actions are a collection of data that you send to the Store. The object must have a type value to define the type of action. The action in Redux is similar to the EventEmitter you've probably used in your Angular applications, and are passed to the store using a dispatch() function.
  • Action Creators: Action Creators are functions that return an action. Action Creators do not dispatch the action, only return it. It is a way to encapsulate your functionality for creating an action.
  • Reducers: Reducers are a function that update the state of the application. It accepts the current state, and the action you are performing. Reducers should be pure functions, meaning they do not have any side-affects such as changing the arguments or calling non-pure functions. The reducer does not change the current state of the application because that would be a side effect. It only creates, and returns, a new state object.
  • State: The state is an object that stores data for your application, such as items in a shopping cart, the user who logged in, or other information.
  • Store: The store is a single object that holds all the application state. It can return the state using a getState() function. It registers or unregisters listeners using a subscribe() function. And it updates state via dispatch() function.

As we progress through this series, we'll cover each item in more detail.

Understanding Redux Flow

Redux has a unidirectional data flow. That means that data always flows in one direction throughout the app. I put together a diagram: Let's look at each box:

  1. Start in the top middle. You have a view which is waiting for action. This could be a user entering data or clicking a button. Technically this doesn't even have to be a view but could be any code in your app, such as the result handler of a remote service call.
  2. When an action occurs, the view will call the dispatch() method on the store and send in the action object.
  3. The store will, in turn, call the reducer() function. The current state and the new state are passed in as arguments. The reducer function will do some magic and return the app's new state.
  4. The store saves the new state.
  5. Then the store calls any listener functions. At some point your code must have called store.subscribe() so it could get notified when something changed.
  6. The listener functions run code and update the view. If they need access to the current state they can call the getState() method on the store.

The process is simple to understand. With a shared vocabulary, we're ready to tackle some code and the next article in this series will create the first Vanilla JavaScript Redux sample.

All Content Copyright 2005, 2006, 2007, 2008, 2009 Jeffry Houser. May not be reused without permission
BlogCFC was created by Raymond Camden. This blog is running version 5.9.2.002.