Marvelous Thorough React Tutorial/Workshop — part 3

This series of articles is written as notes used during the workshop hosted in Gdańsk, Poland by OKE Software Poland. It does not pose as comprehensive and complete tutorial serie for anyone, yet it will be used for workshop aimed for developers that have none experience building SPA using React. I am posting it here as I think some people might find it useful. Please do not hesitate to correct my, if you find me writing nonsense. Also please bear in mind that english isn’t my native language, so forgive my any grammar and linguistic mistakes. My fourth article! Enjoy!

BTW here’s the previous part ->

Plan

Part 3 — JSX, React Components, ReactRouter, StyledComponents

We have finished the last part with setting up Webpack and using the babel-loader to transform our ES6 code to ES5 compatible with most of the browsers, but we also need these tools to transform JSX into standard JS code. Using React.createElement function can be exhausting and make your code hard too read. Especially that pretty much every single developer is comfortable with html and now how to read it and build stuff with it. Many frameworks are using something called templates. These are files that are used to build parts of your web with data dynamically fed into them. Angular had them (with it not so great ng syntax), as well as Ruby on Rails, Django, .NET and every other framework. How does the React cope?

JSX

In the past people much smartet than me, came with this great idea of separation of concerns. In our context this means, spliting the structure of the website (HTML) from how does it look (CSS) and how it behaves (JS). This simple idea have been good enough to settle in the industry for years. If you wanna change the layout of the elements, go to your *.html file. Need to change the background colour or margin? Easy, open you *.css . You want to perform ajax call or check the form for errors before submitting it? Here’s you *.js file to do this.

That’s the theory.

In practice I have seen many times, people hundreds of lines of js code in script tag in *.html file and doing same for CSS. Creating files like homepage.html and writing every single piece of layout there extending far between 200 lines of code. And the CSS specificity? Nope, we write some classes then override them then add some !important declaration and split CSS in files naming them like layout.scss or grid.scss. Instead of reusing what we do, we bloat our code base, we override stuff and end up with unmaintainable code. Creating ‘dynamic’ html by transforming string with the layout and than appending it via JS. Yup, seen that two or even better making ajax request to get script as a response. It felt so chaotic and dirty.

React is something else. We really try to focus on components as separate, composable elements. Our components layout and behaviour is enclosed in one file. It didn’t make any sense to me at first. This wierd XML like structure trying to impose itself as HTML in js file? It was wierd, but it made it case for me once I gave it enough time. So let’s give it a chance and see how this works out.

Let me just remind you what we’re be trying to build:

Master/Detail View

Let’s open our js/App.js file and change it to something more sophesticated:

of course we must run yarn bundle and open index.html file to admire our newest creation. This is the simplest React & JSX component there is. It’s just function returning some familiar looking markup :). We import React from our node_modules, because it has to be in a scope of a module to use JSX.

So yeah, typing yarn bundle everytime we make a change seems like something we could automate, right?

In your package.json file add another script:

"bundle:watch": "webpack --watch"

You will see that webpack will build your files another time, but instead of closing will await for further changes to the files to rebuild what is changed automatically. Change something in App.js, then head to your browser to reload the page. Another useful enhancement that will help us move faster.


Now that we are ready to build our React app, there’s one thing worth mentioning. When using React is worth to look at the design and split it (in your head or maybe even using a sheet of paper) into the components. It’s really profitable to plan ahead and decide what will be the architecture of our components. The core concepts of React is composeability and configureability of components.

thinking-in-react-components.png

This example is taken from React documentation and it presents how we want to approach dealing with complex views. We split them into smaller and more atomic chunks that can be ruesed, so it’s useful to think about your views in terms of small pieces building bigger pieces:

But often when we use React we start building something and than when we decide it’s to big or has to much responsibility we split it.


Ok, let’s go back to coding. How about nesting the markup? Same as HTML. Let us edit the App.js again:

JSX Nesting

Ok now that we’ve imported both React and ReactDOM modules. We can move to our index.html and remove scripts that were including those from node_modules:

One important thing to mention is about ReactDOM this package was previously inside the React node_module and that was fine, but frankly React is just a paradigm. It doesn’t consider itself in what it will be rendered to. That’s why we can use React along with ReactNative or ReactVR.

Nice, still everything is working! Ok let’s work on our TopBar component. We see that it consist of Marvel logo, red background and some text. Let’s handle the background and text first.

Go to your TopBarTitle.js. Let’s rename it to TopBar.jsx and change its content to:

https://gist.github.com/wojciech-bilicki/b66a3b62dc0eaf7dc28beb16a0f1cbf8

And here we come to the point where we can use famous React composeability.

We can move to our App.js file and change it to:

Tada! We compose our first two React components with TopBar being a child of App. Check your index.thml to confirm that it is working still.

I believe this is the time we should consider ourselves with styling a bit. Please keep in mind that this is not the CSS workshop by any means. So I’ll be just pasting most of the CSS code without explenations. There are plenty of ways we could style React components. We can write our css files completely separately and just add them to index.html without concerning ourselves with any of the tools and css-loader for webpack and it would work, but I am sure we would loose the CSS specificity that we are aiming for. We could use css-loader and the approach called css modules and I can’t recommend enough great article written by Phillipe Masset in which he explains this approach:

But I’d like to go for something that I’ve found a little bit more suitable for me, Styled Components:

This are descriptive, configurable and reusable primitives written in JS that have all the things that you love from CSS and more. Why to use them? Well with recent spreading of the idea of css in js, this comes as the most reliable approach. It will help use maintain the modularity and now we can really have everything in one place: structure of the component being defined by JSX, its looks by styled components and the rest of the logic being held in js, all in the same file. This is completely differente from the approach seen in standard apps where we split html, css and js in 3 files.

If you need details and background on this tool I recommend watching:

https://www.youtube.com/watch?time_continue=89&v=bIK2NwoK9xk

Let’s add styled-components by running in our terminal:

yarn add styled-components

K, let’s head to our TopBar.jsx and change it to:

Ok we can see two things from the very beginning. We can easily make our JSX structure more verbose by using styled-components as we change the simple HTML5 header tag to TopBarWrapper. Also we can still use the nesting of the elements known from CSS. We can also use the styled-components to style other styled/component:

const MyFantasticUberUltimateTopBarWrapperIsSoFancy = styled(TopBar)`
background-color: #cccaaa;
`

Which can be extremely useful when you need to tweak the style of given component just a little bit.

Ok, now I’d really like to add a font to the project. Let’s go to our index.html and change the head tag to:

Reload the index.html to see our brand new font in play. Lookin’ good!

So before we can move on, let’s try adding (yeah, you got it right!) more useful tools. For starter I’d like our webpack config to be aware of our ESLint, too. We got that integrated into VSCode, but adding it to webpack won’t do any harm ;). This means we need another loader. Head over to terminal and type:

yarn add --dev eslint-loader

Then open our webpack.config.js and change it to module entry to:

We add a rule to run every .js, .jsx file through the eslint-loader which pickups our .eslintrc settings. Additionaly the enforce: 'pre' settings enables us to run this before the build step so that our precomplied code is poured into the ESLint.

Now if we run yarn bundle:watch we can see ESLint seamlessly integrated with Webpack:

ESLint integrated with Webpack

For the time being we are loading our file into the browser from our disk, which was fine for what we done until this point, but sooner more than later we’ll need some kind of local server. Most of you probably heard of things like XAMPP, Apache, Nginx or other server solutions, but we don’t need the gorilla holding the banana in the entire jungle. As far as I remember Django and Ruby On Rails come with nice solutions where you can just type rails s in your terminal and run your local server. We could also use Express.js server or python simple http server, but lucky for us Webpack comes with ready solution. Let’s add webpack-dev-server to our project:

yarn add --dev webpack-dev-server

and run it with:

node_modules/.bin/webpack-dev-server .

Now you can go ahead to localhost:8080 and see that we are using local server to serve our app! It will rebuild faster because all is kept withing the memory. Let’s tweak our webpack.config.js a little by adding the entry after module:

devServer: {
publicPath: '/public'
}

This is for serving our static files correctly. Ok just to finish setting up the devServer let’s move to our package.json and add another script:

"start": "webpack-dev-server"

Now we can type simply:

yarn start

And we have our project up and running!

React Router

This pretty much sets us up for the future development of our app. There’s just one last thing I’d like to present in this part. Most of the server side rendered solutions where pages are rendered on server and than served to the client are using the concept of router (again frameworks like Ruby On Rails, CakePHP or Django come in mind). Router are rather simply to setup, you specify the url and connect to given controller and than proper page is evaluated based on url and it parameters and sent to the client. There’s natural need for this kind of stuff for the SPAs, too. Angular comes with built-in, opinionanted solution for this. When it comes to React, things aren’t so obvious. Remember that React concert is only view rendering. Still we need an approach to serve different content based on the user location in our app. There’s plenty ways you could approach routing with React, but for some time now the react-router placed itself at the top.

Guys behind it devoted a lot of work to react-router. They broke some backwards compatibility along the way, but since the v4 was released things are rather stable I must say. Ok let’s add this one to our project:

yarn add react-router, react-router-dom

Again the concept of routing isn’t particulary reflected only in DOM area, yet it will our main field of interest that why we’d like to have both packages installed.

and rearrange our files a bit. Create new file Master.jsx and move the code from the App.jsx there:

We also added the Link component from react-router-dom which is a wrapper for the good old <a> tag. This will point us to our second page with the details of the hero

And than we’d like to finally add our router to the App.jsx

And here it is. The Router itself isn’t anything else than Higher Order Component which enables us to render proper React components based on the user location. Here we define to locations and two components that should be if the location is matching to the path parameter. Ok this seems in order. Let’s try and click on the link that we’ve just rendered!


Not what I’ve expected, to be honest. But yeah there’s some logic behind it. With the /detail url both components are matched. What we’d really like is to render only the first component that is matching our pattern precisely. What we need is to wrap our Routes in Switch component like this:

Now it should work as expected! If you want to get into more details about the React Router the documentation on their page is rather solid, but I’d also recommend reading through article by Paul Sherman:

And that’s it for this part! We’ll seriously start discussing React in the next part! Cheers!

A single golf clap? Or a long standing ovation?

By clapping more or less, you can signal to us which stories really stand out.