Creating Jumble (part 2: wireframe)

If you are coming here directly and have not yet viewed part 1 you should. Over there I go through the structure of the app and why the structure is the way it is. Also I talk about the app it self, what it should do and how it should look. Well, lets get to it…

Views

Now that we have the structure all set up lets expand our application by adding some views. To keep this as simple as possible lets keep our home and add a jumble view that has overview to list the jumbles a user has and a detail view for a specific jumble.

The overview is simply going to render a list of things and the detail will render some detail about one of the items listed in the overview. Lets not go into any specific about what we list since we are simply providing a wireframe for our application at the moment.

First of we make the view by adding a jumble folder into our view folder. This folder will hold the jumble view. Now in that folder we have our overview and detail folders for their respective views and we end up with a src/view folder structure like this

bjorgvin@computer jumble $ tree -I 'node_modules'
.
└──src
└── view
└── jumble
├── detail
└── overview

Lets populate the overview and detail views with simple components named Overview and Detail so we have something to view. Start with the src/jumble/overview/Overview.js and its src/jumble/overview/index.js counterpart:

And then our src/jumble/detail/Detail.js and its src/jumble/detail/index.js counterpart:

Now we have our two simple components that represent our jumbel view but we have not yet wired them with the rest of the application.

Routes

Lets wire our views to the reset of the application. To do that I add a src/jumble/routes.js file that will add the routes a user must take to see the view and of course an src/jumble/index.js for the folder.

What we have here is a simple route configuration that holds our components and the way to navigate to them. We have our /jumbles for our overview and our /jumbles/:jumble for our detail where :jumble will act as a parameter for our detail view later.

Even if we have done all of this we are still not able to view our new components. This is because we need to wire our new routes to our old routes. This we do by adding our new routes to the root routes configuration file src/routes.js and our new updated file will look like this

Now we added an import for our /jumble routes and a Switch around our routes. We need the switch so we only render the first route that matches. If we didn’t have the Switch we would always redirect to /jumble like our bottom Route dictates.

Now if we run our application and navigate to the root / we will have our home like before and if we navigate to /jumble we will see our Overview component and if we go to /jumble/anything we will see our Detail component rendered. Any other route will result in a redirect to the /home route.

Now our structure should look like this and we are ready to take our next step in the evolution of our application; getting some data.

bjorgvin@computer jumble $ tree -I 'node_modules'
.
└──src
└── view
└── jumbles
├── detail
│ ├── Detail.js
│ └── index.js
├── overview
│ ├── Overview.js
│ └── index.js
├── index.js
└── routes.js

Platform

Now we would like to get some data from our platform so we need to create a folder in our platform folder named jumble and put our actions, sagas and reducers there. So our platform structure will look like this:

bjorgvin@computer jumble $ tree -I 'node_modules'
.
└── src
├── platform
│ ├── home
│ │ ├── actions.js
│ │ ├── reducer.js
│ │ └── sagas.js
│ ├── jumbles
│ │ ├── actions.js
│ │ ├── reducer.js
│ │ └── sagas.js
│ ├── reducers.js
│ └── sagas.js
├── reducers.js
├── routes.js
└── sagas.js

As you can see we have an identical structure to our home folder. The actions we need to get started are fetch to fetch our jumbles and a resolve when all the jumbles have been, well, fetched.

Lets take a look at the src/platform/jumbles/actions.js file and see how simple it is to create those actions.

We have a fetchJumbles action that will be responsible for triggering a saga to fetch all the jumbles. Also, when all the jumbles are fetched the fetchJumblesResolved should trigger the reducer to update the application state for our views to be re-rendered.

Lets look at the src/platform/jumbles/sagas.js to see how the actions are used to actually fetch jumbles

Like you see we are watching, hence the name watchFetchJumbles, for the fetchJumbles action type and when an action of that type is dispatched we would like our onFetchJumble method to handle that action.

What that method does is simply dispatch the fetchJumblesResolved action holding some hard-coded jumbles. It is done by using the put method from redux-saga/effects.

Since this would be done by calling a server, and that might take some time, we add a small delay of 1 second before we resolve the fetchJumbles action. You can change the delay time or skip it all together.

We must add our sagas to the parent sagas for it to be run with other sagas in the application so we add it to our src/platform/sagas.js like so

Even if the sagas are now ready and part of the application we need to dispatch the fetchJumbles action for it to activate. This we do when our Overview component loads. And in order to do that we need to connect our Overview component like we did with our Home component

And now we have access to the fetchJumbles action and we can call it when the Overview component is mounted by adding the following method to the component

Now when the component is mounted it will call the fetchJumbles method that will dispatch the fetchJumble action. The action will be picked up by the our saga that in return will dispatch the fetchJumblesResolved action to be caught by reducer that will populate the application state.

At the moment there is no reducer handling the fetchJumblesResolved action but in order to get the jumbles into our application state we need that. So, we create our src/platform/jumbles/reducer.js to do just that

Identical to the src/platform/home/reducer.js we have the initial state holding our jumbles in an array and we handle a *Resolved action by populating the application state with the jumbles found in the action payload. We also have a selector called getJumbles that will fetch the jumble array within the application state. This selector we will use in our Overview component to get the jumbles from the application state so we can render those jumbles.

But first we need to add the reducer to our parent reducer for it to take part in the reducers of the redux store. Simple enough to do by adding a reference to our new reducer in src/platform/reducers.js like seen here

Now that we have our reducer available we can add the jumbles from its selector to our connected Overview component found in src/view/jumble/overview/index.js file like

We simply add a jumbles prop to our connected Overview component that will get its value from the getJumbles selector method in our src/platform/jumbles/reducer.js

Now that we have everything wired up all we need to do is use our new props in our Overview component

Now all we need is a way to navigate to our Details component for each of those jumbles. This we do by importing Link from react-reouter-dom and for each of those jumbles we render a link to the Details component like this

But our Details component is not connected to the application state and receives only the jumble id as parameter like before. What we would like to do is use that id to get the jumble from the state in order to render something meaningful about that object.

So we change the src/view/jumble/detail/index.js to export a connected component and provide a way to get the given jumble from the application state.

Like you can see we are using a method from the platform reducer to get a single jumble. This method doesn’t exist so we add that one in our src/platform/jumbles/reducer.js and make sure to indicate if the jumble exists or if it has not yet been fetched

Now we can add some rendering for a specific jumble in our Details component

Now that we navigate to /jumble we see a list of links to specific jumbles and when we click on one of those we render details about that jumble. However, there is a problem when we navigate directly to /jumble/:id since we are not mounting the Overview component and as you might remember that is where we are loading our jumbles. What we get is an error saying our jumble instance is undefined.

What we need to do is fetch the jumbles when the Detail component is mounted just like with the Overview. This is simple enough since we have all the methods we need and our Detail component is already connected to the application state. So we add the import the fetchJumbles method from the platform and add that to our connected component so it gets available through the Detail components props.

And in our Detail component we add a componentWillMount method and call the fetchJumbles method there.

We have a problem with this since we are indicating we need to fetch our jumbles twice and our saga simply goes to the server but we don’t want it to that if it already has. So, we need to do some changes in our saga in order for it to fetch jumbles from the server only if the jumbles are not already in our application state. We change our src/platform/jumbles/sagas.js

We use our getJumbles method from the reducer to access that application state using select method from redux-saga/effects to get jumbles from the application state to check if we need to fetch the jumbles from the server or not.

Well, back to the Detail component since we still need to render the jumble or, if it is not yet available, render some text indicating that we are loading the jumble.

But what if you enter an id that doesn’t exist and never will? Well, as we saw in our reducer we are returning a jumble if it is found, undefined if not yet loaded or null if we already loaded all the jumbles but the one you are requesting is not there. This information we use when rendering the Detail component.


When we go to our application we are met with the Home component showing the welcome text. But there is no link or any other means to get from there to our jumbles Overview component.

We change that by going to our src/routes.js file and add a nav element holding some Link elements from react-router-dom

It looks like our wireframe is complete and we are ready to navigate through our application.

Note: To fetch this part of the code you can fetch the view branch from GitHub

What if you come there for the first time and have no jumbles? You need a form to create one and a persistent store to store them. Coming up in part 3 is Form n’ Storage; lets go…