A while ago I posted about how we built a new website and Status Manager, the latter of which I learnt and built using ReactJS. This blog post is going to go through some of the things I had issues with learning ReactJS (not that many, its fairly straight forward once you get your head around with how it works).

Why I Learnt ReactJS

ReactJS has been on my radar to learn for some time, but was always put off by the the way that it was described as it being a single page web app. This put me off initially, as this sounded a like there was only possible to have a single page, and I wrongly thought this then meant you can't browse direct the user to other pages, such as logins, dashboards, account settings on the app, and it was only suitable for basic app. This was clearly wrong, when I looked into ReactJS properly you can have multiple pages from the users point of view, the reason why its considered a single page app, is because every request, goes to an index.html, and that page, renders differently, based on the routing path that is used. Once I researched ReactJS properly, instead of making incorrect assumptions, I then decided to crack on and learn ReactJS.

When I learn a new language, I always start with some tutorials, training guides etc to get a basic understanding of the concepts, then start working on a project and learn as I go, I always find it better to learn while doing then just following a tonne of different training guides, so this is where I started building the Status Manager pages.

I started off with creating a login form for the admin section of the status manager, worked out how to perform the styling the individual components to make up the form, and how to make a POST request to the API for it. Got that working, and then this was the next stage, how I can then render a different page to the user.

This is where I went wrong straight away. When you first create the project, using the following:

npx create-react-app my-app

When you first create the project, you get an App.js which is the start point of your project. At the start of the project you get the ReactJS Demo Page. When I was first creating my login form, I deleted ReactJS and created LoginForm.js and updated my package.json (this provides some settings for the project such as how to start, project dependencies etc) to start LoginForm.js first. This was fine, until after returning a successful login response from the API, I needed to direct to another user, and this is where I discovered that deleting App.js was a mistake.

This part is the hardest part I found in ReactJS, there wasn't a lot of documentation on this, and from what I found, there were several different ways of doing it but none of the examples worked, not sure why they didn't work, if it was to do with wrong versions of ReactJS I'm not sure.

In order to find a solution, I posted a question on Stackoverflow and got an answer to the problem. Once I understood what I needed to do, I saved a backup of my LoginForm.js component and then deleted my project.

I started my project again by using the npm create-react-app command and this time didn't delete my App.js.

Instead, I modified App.js to add the routing paths. But first, I needed to install react-router-dom. Once installed, I then created a BrowserRouter which detailed the paths of the individual pages and what components they render. For example, I had the following in the return method of the App function with App.js

<BrowserRouter>
	<div>
    	<Switch>
        	<Route path="/" render={(props) => 
            	<LoginForm {...props} /> } exact />
            <Route path="/dashboard" render={(props) => 
            	<Dashboard {...props} /> } exact />
            <Route render={(props) => <NotFound  {...props}/>}/>
        </Switch>
    </div>
</BrowserRouter>

Inside the Switch tags are the individual routes and what components what will render. So if someone goes to the root domain, the LoginForm.js component will be rendered. If the user then clicks a link so the URL is now /dashboard then the Dashboard.js component is rendered. The last route is there as a catch all. If none of the paths are matched, then my NotFound.js component is rendered instead of a default server not found or ReactJS error.

Deploying my First ReactJS Project

After the project was completed and I was ready to install it on the live Boardies IT Solutions web servers, we first needed to build and compile the project. To do this you run the following command:

npm run build

This will compile your various scripts into a script bundle along with your assets such as images and stylesheets and will be located within the build directory of your project folder. The contents of this build folder can then be transferred to your web server of choice.

At Boardies IT Solutions I use Apache as the web server, so after uploading the build directory and updating our Apache Virtual Host configuration with the new path we then browsed to the site, and low and behold it all worked we had a login page all working in ReactJS. I logged in, the browser successfully changed URL to be /dashboard and then I was presented with the standard Boardies IT Solutions 404 Not Found error, huh why is that.

There's a pretty simple explanation. As mentioned earlier, ReactJS is classed as a single page app, as all requests go to index.html, and index.html based on the routing paths within App.js dictate what components get rendered into index.html. When you are developing you are using the ReactJS development server on port 3000 by default which handles this automatically, but when you build the project and put it on Apache, or any other web server for that matter, Apache doesn't know that everything should go to index.html. Therefore, when I logged in and the browser changed location to /dashboard, the browser tried to do a GET request to /dashboard/index.html which didn't exist.

This is a fairly simple thing to fix. You need to ensure that Apache has the AllowOverride directive turned on for this virtual host so that you can use an .htaccess file to override the settings.

Add an .htaccess file to the root of your project directory add the following

Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]

So what does the above do

The first line Options -MultiViews disables the MultiViews directive. This prevents Apache from trying to automatically add an extension on to the URL path based on existing files. I don't a huge amount about this particular directive, but there's this Stackoverflow post that explains it a little.

The next lines are the important ones. It turns on the RewriteEngine and forwards every single request no matter the URL path to index.html. Therefore, it doesn't matter if you go to domain.com/ or domain.com/dashboard the request goes to index.html and then ReactJS successfully works as index.html renders the App component which then renders your specific component based on the URL path.  

Conclusion

Although I hit a couple of hurdles during the development, this is to be expected when learning a new language and/or framework. In general though the guides and what's available on a Google search is fairly good and the way the framework works, is fairly simple to understand and get started developing in it.

I've come to really like it and found that I've been able to progress fairly quickly on a project and do some more custom things, where doing it the old way with creating several <div /> and wrappers and manipulating with a bunch of javascript and JQuery. The code in ReactJS is much cleaner and much easier to get more sophisticated layouts and better UX and I've found less likely to get tied into a rabbit hole of bugs with JQuery and DOM manipulation that you can sometimes get into as the code becomes more complex.

I will likely continue development for our other projects using ReactJS. I'm currently working on a new desktop application making use of Electron to be able to build native desktop PC/Mac/Linux applications but using ReactJS to create the UI.

My new crash monitoring service that we announced that we will be working on, Crash Catch is also being built using ReactJS.

We plan on having a blog post about Crash Catch in the not too distant future now that the development work has started.

I'm by no means an expert in ReactJS and there's probably a lot I still don't know or things we may be able to do better, so if you have any feedback, advice or any comments in general, then please let us know.

One thing I would really like to know is what your thoughts are on source control for ReactJS projects and including the node_modules folder. There's a lot of contradictory information on this topic and there doesn't seem to be a right answer. Some say, you don't need to import all of the node_modules in to source control, they can be automatically downloaded/installed based on the versions that are included in the package.json. However, some say that you should, due to situations where packages are removed from NPM, although this is uncommon, but if this did happen, you wouldn't have a required project therefore causing your project to fail and have to find an alternative, whereas if node_modules were imported, the module would still be available for use causing little hassle if you needed to do a quick fix for a bug, giving you time to migrate to another option when convenient. I'd really like to hear what your thoughts are on this.

Bear in mind, if you do import node_modules into your source control, be prepared that it will take quite a long time.