React is a java script library that detects application state changes and serves up different views depending on the state. It is currently used by Facebook and Instagram to create what is known as a Progressive Web Application. PWA’s are the next big thing on the horizon for the web, combining the best of a website with the best of an application. Lets dive right in!
What You Need:
You can make PWA’s through a number of different JS libraries, including:
- Angular.js
- Vue.js
- React.js
For our purposes, we’ll choose to use the most active software library, React!
React Developer Tools
Depending on your browser, you’ll want to download the React Developer Tools (Chrome Store Link).
What is React?
React is a javascript libary for creating user interfaces. We create reusable components, and these components display data as it changes over time. React has great documentation at Reactjs.org to help with development.
React hooks into the DOM, or document object model, that creates the structure of HTML elements. DOM API refers to how these elements are updated and changed. React made updating the DOM faster with DOM Diffing.
Dom Diffing occurs when the browser compares the already rendered content with the new UI changes that will be made (by submitting form, etc.). React detects the differences and makes only the minimal changes, allowing for speed optimization. DOM Diffing actually compaes the Javascipt objects, making the changes faster to implement than when writing or reading objects on the DOM.
In essence, React sits between the DOM and the Javascript logic layer, so whenever we use Javascipt to interact with the DOM (for instance, when we getElementByID or when we change classes), we actually interact with the React.js virtual DOM, which interprets our requests and only updates the physical DOM as necessary. Updating the DOM is slow, so React makes minimal DOM updates.
Setting Up Local React Projects
When working with React, we want to have an efficient build workflow to allow for our code to be optimized (babel, ES6) and we want to use the best next-gen features to make developing faster and easier and less error-prone.
To do this, we need a Dependency Management tool, like NPM or Yarn. I’ll use NPM, node packet manager, myself because I am more familiar with it.
We also need a Bundler that allows us to write module code then spread it out over the application. I’ll be using Webpack.
We also need a compiler to transfer our next-gen javascripts into code that can be deployed on the largest number of browsers possible. I’ll use Babel and it’s presets for this compilation.
Finally, we need a local development server to test our code and run our apps locally. This give performance benefits and allows us to hot-refreash the server, or refreash the page whenever we save one of the files.
The very best way to do all of this is to use the create-react-app repository created by Facebook. Use NPM to install it, then run create-react-app app-name from the development folder to create a new project called app-name. CD into app-name and run npm start to fire up the server and get started.
JSX
Javascript as XML or HTML in Javascript, JSX is a hybrid stynax that combines HTML and Javascript in a way that allows us to write components more quickly. We can write HTML (mostly) inside our JS file and have Babel transpile the code into functional JS. We can use HTML element tags and even apply classes to our elements if we switch our the class keyword (which is already registered in JS) with the className keyword.
There are some limitations, however. We only want one root element returned by any component. This means that we only want one <div> returned, and within that we can have multiple children elements. ES6 has loosened this requirement, but it is a best practice to only return one parent element, then have as many children inside that element as you would like.
Creating Components
In React, everything is a component. Components are reusable pieces of websites. Any display or grouping of displays can be made into components.
In it’s simplest form, a component is a function that returns JSX. When creating components within React, there are a few best practices:
- Hold related components in a folder
- Capitalize the first letter of a component name at the folder level and the file level.
- Use the name to describe the purpose of the component
- Give your function inside your component the same name as the component itself.
Props
Components receive properties, which can be pulled into the component and interpolated. For instance, if you have a Person component <Person> and the return from person is <p>Im {name} and I am {age} years old!</p>, then you can pass data from the component to the function by setting an attribute <Person name=”James” age=”34″/> . You then need to access the attribute from the props object (can be any name, but best practices is “props”) that every component already has.
<p>Im {props.name} and I am {props.age} years old!</p> will pull in the attributes as properties of an object and allow them to be accessed for the return.
We can also write HTML between the opening and closing component tags. <Person>Im Super Cool</Person> can be accessed by using the children property from the props argument. So {props.children} will return anything between the component tags.
States
Sometimes we don’t want
// for components created by extending the base Component (and only these), we can use state. Props are passed in from outside the component, wheras states are managed inside the component. Use state with care and try to use arrow functions to create components when possible. State is a JS Object.
DeBugging Errors
Error Messages
Look at the console to see any errors on the page. Most of the time, you will get a line number which will help you see where the error occured in your code.
No ‘…’ Property on Undefined
This error is thrown when you try to access a property on an object that is undefined.
Logic Errors
For errors in logic that do not throw error messages, just break functionality, it is best to use the sources panel on the web developer toolbar. With this panel open, you get access to the source files for your project.
IMPORTANT – You get access to copies of the actual source files, not the compiled files sent to the browser. This is a very powerful feature.
Click on the line number where you feel there might be an error to set a breakpoint. This runs just small pieces of the code. When set, try to interact with whatever isn’t working and you can walk through the steps to see what is being returned when and how your data flows across your application. Learn more about this!
Error Boundaries
There are times when you will be working with API’s or getting data from 3rd party servers and they will fail. Of course, sometimes they will work, so you need to be able to handle the error gracefully if it occurs. This is where error boundaries comes in. To do this, create a new component called “ErrorBoundary” in a folder of the same name.
You will create an ErrorBoundary component by extending the base component and adding some logic to handle the error. You then need to import your new component to your base App.js and wrap display components in your ErrorBoundary component. It is a higher order component, meaning it is a component that wraps another component, providing more functionality. It is similiar to Radium.
Do Not cluster entire App.js in ErrorBoundary, only the components that make sense for detecting errors. Use them in code that may fail, not in normal code. Only used in cases where it might fail and you don’t have control of that.
ErrorBoundaries allow the App.js to function fine, just replacing any breaking components with your ErrorBoundary code.
Understanding Components
Components should be very focused on, if possible, only do or control one thing. The root App component should be mostly responcible for managing state, without too many UI pieces in it. in other word, App components should have lean render methods without very much JSX to process.
Use the folders to better explain what is happening in your App. For example, we have a Person folder that handles logic of a person card. We also have a new Persons folder that will handle the list of Persons. As Person is a single instance of an item in the Persons, list, we will put the Person folder in the Persons folder, nested.
We would also likely have an assets folder for our images and other media assets. We might also have a containers folder for our container elements like App.js. In essence, we only really want index.js in the src folder, everything else should be broken up and grouped.
We also want to use as many functional components as we can in our project. Finally, we will create a Cockpit folder in the src folder with a Cockpit.js file that will
Functional (Stateful) Component vs. Stateless Components
Stateful
- containers
- extend base Component class
- access to state property
- lifecycle hooks
- We can access State and Props via this keyword
- this.state.XY or this.props.XY
- ONLY use stateful components if you NEED to access state or lifecycle hooks
- otherwise, do not use these
Stateless
- functions that receive props
- NO state property access
- NO lifecycle hooks
- We access state or props methods with props keyword
- props.XY
- we receive props as an argument
- Use stateless components in all cases EXCEPT changing state or lifecycle hooks.
Components can be created with class that extends the root component or components that are really just functions that return something. We want to create as many functional components as we can because they have a narrow focus and a clear responsibility.
Functional components are most concerned with the presentation of data. They render JSX and they contain the logic to render that JSX correctly. Functional components should NEVER change or manage the application state. The more our app grows, the more difficult it will be to manage state, so we want state managed in as few places as possible. We want to pass state to our functional components through props, offering us many advantages. We can give access to the functions the edit state (with props), but no components are able to change state.
Use class based components as little as possible, only when it makes sense.
Component Lifecycle
When React instantiates and renders component, it runs through multiple lifecycle phases. For stateful components, we can define methods to run different code during different lifecycle phases.
- constructor()
- componentWillMount()
- componentWillReceiveProps()
- shouldComponentUpdate()
- componentWillUpdate()
- componentDidUpdate()
- componentDidCatch()
- componentDidMount()
- componentWillUnmount()
- render()
Component Creation Lifecycle – Methods
- constructor()
- Only used in Stateful components
- Initially, constructor is executed and class/component is instantiated with any received props.
- When used, we MUST access the super method and pass it props
- super(props)
- We can also initialize the state in the constructor, but be careful of any side effects
- watch when reaching out to web server from constructor as the data cannot be relied upon. DO NOT have requests which come back and then edit the state of the app. This will inevitably break
- componentWillMount()
- fired right after the constructor() method
- used to update state or perform last minute optimizations, but it isn’t used much anymore
- render()
- fired after componentWillMount()
- defines the presentation of your application
- prepare and structure your JSX code in the render() method
- AFTER rendering JSX, it will then move to render any child components that are referrenced.
- componentDidMount()
- fired after render() and rendering of all child components
- boolean which responds whether component was successfully rendered or not
- this is usually the point where we reach out to web servers for 3rd party data
- be sure to not update state, as this will trigger a re-render and could break the app
To convert a functional component to a stateful component, simply change the const statement to a class statement of the same name that extends component. Then import the named { Component } and create a function body with a render(). You then return all JSX within the render method, then export the updated component with the export default.
Component Lifecycle By Updating
There are two ways to trigger an update, either through props or state. Within your app, if the props (children) change in any way, an update is fired. The process looks like this:
- componentWillReceiveProps(nextProps)
- this allows us to initialize the current state with our given props. Now we can change the state in the component but still get the base state from the outer props.
- watch for fetching data in this trigger
- shouldComponentUpdate(nextProps, nextState)
- This method may actually cancel the updating process. We can pass true to this method to continue updating, or false to stop it in its tracks. In the other methods, we never return anything. If we return false, it saves our App a render, thus making it more efficient. However, the state will not change, so think this through. This trigger is used with logic to decide whether to continue with the update.
- componentWillUpdate(nextProps, nextState)
- if you continue through update, you reach this trigger. This is the better place to synchronize state to props because at this point you already are committed to the update.
- render()
- If you reach this trigger, our JSX is rendered and React is informed on what needs to be updated
- Update Child Component Propers
- This might also trigger the child components to re-render
- componentDidUpdate()
- This is where you should look out to the web, but do not change any state here
Update Triggered By State Change
- shouldComponentUpdate( nextProps, nextState )
- This trigger can be used to cancel the update process. Use with logic to decide whether or not to continue
- componentWillUpdate()
- same as above
- render()
- Render Child Components
- componentDidUpdate()
The only difference between the two lifecycles, whether trigger by props or state changes, is the first trigger, componentWillReceiveProps().
PureComponents
We can change our extend call to extend PureComponents if we first import them in the declaration. With PureComponents, we already have the logic for shouldComponentUpdate() installed and the component will check it’s own properties to see what was updated and whether these updates need to be passed to be virtual DOM. PurComponents also apply to stateful components, so they can be used in the App.js
Only use PureComponents when you know that updates might not be required. It has performance hits in the automatical shouldComponentUpdate() call, so if we know that the component will always update, we waste resources on the unnecessary method usage.
Rendering and Updating Process
The update process in react filters from the top down. Also, Components nad child components will update whenever the state OR the props change.
How React Updates the DOM
The render method does not render your JSX to the DOM. To React, Render() is a suggestion as to what the HTML on the page should look like at certain states. Before React renders anything to the DOM, it first compares Virtual DOM’s. Virtual DOM’s are DOM representations in JavaScript.
React looks at the current Virtual DOM, the HTML on the page, and compares it to the Virtual DOM that is created when the page re-renders. If these pages, the current and the newly re-render, will have the same HTML, then React will not render anything to the real DOM.
The Virtual DOM is much faster and easier to manipulate than the real DOM, which invokes HTTP requests to manipulate it. Even when the Virtual DOM detects changes and the real DOM is updated, React only changes the portions of the DOM that were updated, thus minimizing requests.
Changes in React 16
We know that we can only have one root element in the render() method, usually a div, and then we can have children inside that container element. In React 16, this has been loosened an we can return arrays in the render method. Of course, these arrays that we return must be mapped to JSX objects, but we have the ability to add multiple adjascent elements at the root of the render() method. PRO TIP – When using this method, each array item must have a key value for React indexing.
You will not usually return arrays, however, except when returning a component that handles the rendering of a list
Higher Order Component
These are just like other React components, expecpt they are not presenational. They only wrap other React components, providing them additional functionality. We can use a HOC to wrap our JSX, thus allowing us to return adjascent elements with a nominal wrapper, even though the wrapper doesn’t do anything. We no longer get errors from React. This is used when you either can’t or don’t want to add wrapping divs, most likely because your CSS framework doesn’t allow it.
Using setState Correctly
If you plan on using logic with your state, for instance, using a counter that adds up clicks, then you can’t update state with this.setState. This is because setState runs asynchronously and can be fired by multiple different components, changing the scope of this multiple times. Depending on when you’re call is fired in the queue, you can get varying results.
The best way is to place a function in the setState argument. When mutating state, if you rely on the previous state, you must create a function that takes in the previous state and any props, then returns the new state
Validating Props
If you plan to export your components for use by other developers, you will want to restrict the prop types that can be used by your component in order to prevent any data from going somewhere unintended.
We do this with a package that we add to React. The package is called Prop-Types. So run to your command prompt and use the command: npm install –save prop-types to install it on your project. We then get access to the PropTypes object which we can use to specify what type of data we can take in for the prop. PRO TIP: Do the specification of PropTypes directly after the class declaration. We are editing the class after it’s instantiated.
We then get a helpful error message telling us what prop is wrong and what was expected. This does not work on functional components, only those that extend the base component.
Using Referenes
This is mostly invoked when trying to control the focus of an input. We have something called reference which we can set on an input element. Ref takes a dynamic input (function) and in the function you set up reference to the element. Once again, ref is only available on stateful components (those that extend the base class).
Ref will add a property to the class that can be used as soon as the render() method is invoked. This means you can access the property in componentDidMount(), which fires after render(). DO NOT use this technique for styling or displaying, it is only for narrow use, like focus or media playback
Planning Your React Apps
- Component Tree / Component Structure
- Plan the component tree by taking your concept or idea and splitting the pieces of your idea into components.
- You want to think about what should go in its own component, and what shouldn’t
- Plan the component tree by taking your concept or idea and splitting the pieces of your idea into components.
- Application State (Data)
- Determine the data you plan on using and manipulating in your application.
- Components vs. Containers
- Now you want to decide which components should be stateless (functional) vs stateful (containers).
Reaching Out To The Web
React is a library for creating user interfaces. That is, React is responcible for the resultant HTML that is displayed in the browser for the user to interact with. We are able to make HTTP requests and AJAX requests from the browser to the server-side backbone to query databases, and access API’s
How to send HTTP Requests (Single Page Application)
Single page applications feature strong decoupling between the frontend code and the backend server. The React App and the server still communicate, but they don’t use HTTP requests. When React requests data from server, we aren’t returned HTML pages, we get JSON data. If we wanted to create a resource on the server, we would also use JSON sent from the browser to the server. The communication language between server and React app is JSON.
Your server is usually a RESTful API, only exposing server endpoints to which you can send CRUD requests.
When making requests, we can use the javascript {XMLHTTPRequest} object to create our API connection. This can become combersome, however, so I recommend using Axios. Axios works great with React because it is full javascript, however it isn’t connected to React and can be used in any JS project.
Because HTTP Requests are side effects to our main app functionality, the natural place to add HTTP Requests is in the componentDidMount() step of the component lifecycle.
Because the get requests that axios gives us access to fire off asynchronously, we will send a request and then the page will still load normally, without waiting for the return data. To get around this, axios uses Promises, a new javascript object added to ES6. Promises are functions that are executed when the request is resolved. This allows the code to be run, and when a requests is sent, that request returns whenever it does, with the function (promise) then applied to the returning data.
Routing
Another common feature for websites is routing. That is, serving different pages to different requests. React does not offer this functinoality out of the box, however, we can use a router package.
We do routing because we want to offer different pages for the user to interact with. Even if our application fits on a single HTML file, we can give the user interaction points with routing. Because we don’t have multiple files, we can use JS to render different pages for different paths.
We are basically re-rendinger parts of the page depending on how the user is navigating. The router package we use must perform various functions:
- Parse the URL / Path – The package must detect changes in URL and serve data depending on the path.
- Render / Load the Appropriate JSX – The router will load different JSX or components based on how the URL changes.
Code Splitting / Lazy Loading
There are often times when we will not want the browser to download the full code for every component, only the components that can be rendered to the screen. The process of splitting your HTML document download to only the necessary pieces is called code splitting or lazy loading. React supports this!
Code Splitting depends heavily on your website configuration. If you make you application with create-react-app and react-router V4, you have access to this feature.
When Deploying Your APP on the Web with Routing
When you place your App on the web, your React App will be aware of your routes, but the server holding your app will not be. All the React programming is loaded on the index page, so the server must be set up to handle this. We have to configure the server to forward all requests to the index page in order for our React app to function properly.
PRO TIP – Make sure to forward 404 errors to your React app as well, so we can handle them there. Also set the basename in your BrowserRouter component.
Understanding State
In React, state determines what is rendered on the screen. State management can be very complex as application grows. React exposes a built-in state property that can be used to manage state, but this comes with issues:
- Passing ingredients from component to component can be difficult
But why is it difficult. Why can’t we access state in a global sense, that is we can access any state param from any component anywhere on the app.
React does not, ummm, react to global state changes. This is actually what makes the software package so efficient and fast. As a compromise, Redux was created to store these global state params while maintaining speed and reliability across your application.
How Does Redux Work?
Redux is a 3rd party library that Redux offers us a flow of data that allows us to get React to change on global-esque state changes.
To do this, Redux sets up a central store. This central store is used to store the entire application state. It is a gigantic javascript object.
Components want to manipulate app state, but they can’t talk directly to the state held in the central store (Immutability of state). This is where Redux steps in.
Redux uses actions. These actions are dispatched from your JS code. Actions are information packages with a pre-defined operation. They can also hold a payload, so if products are being sent to a cart, we would need to also tell the cart exactly which products we are sending.
Actions don’t reach the central store and they don’t hold any logic. They are simply messengers.
These messages speak to the methods that actually interact with the store, the reducers. Your action reaches out to your reducers, where the reducer then checks the type or operation of the action, and then runs the code that is tied to that operation.
Reducers are functions that receive actions and the old state as input, which then spits out an updated state. The reducers require code that has no side effects (calls to the web). Its input => output with no delay in processing while retrieving requests.
The reducer then sends the updated state to the central store, which replaces the old state with the updated state. We then need to return a new state, which can be based on the old state, but is technically a new JS object. Since all objects are reference types, by using a new state object, we don’t obliterate the old one.
Once we have the updated state in the central store, we use a subscription model to then send that state to the component. The central store will trigger all subscriptions whenever the state is updated. The component can then subscribe to these store updates, which will be passed from the subscription to the component as props.
Types of State
Whetehr to use Redux or not depends on the size of the application. If project is small, will take longer to set up than worth it. large projects definitely benefit from Redux. What should you manage in Redux?
- Local UI State – Ex. Show / Hide Backdrop – Change the state to alter the UI – We should handle this without Redux, though we can use Redux if we wished
- Persistent State – All Users or All Posts, etc – Store the data on a server database, but use Redux to manage the connections to this data
- Client State – Is User Authenticated? or filters set by user – This is the perfect case for Redux because it might affect multiple components in application.
Middleware
We are not supposed to do any API calls or return anything from the web during our action subroutines as Redux does not natively handle asynchronous code. We are able to fix this with the inclusion of Middleware.
Middleware is code that gets added after your actions are dispatched but before they hit your reducer. We can run this middleware without affecting the performance and operation of our action – reducer set up.
Actions still reach the reducers, but we can then do something with the actions without affecting the reducers.
Authentication in React
Instead of storing a session cookie on the server to authenticate users and ensure that every page they request is permitted, Single Page Applications don’t work this way. We can, of course, set the session cookie to authenticate the user, but it is possible that no other pages are then passed, so the server would not see requests to determine authentication.
For these reasons, our React Single Page App, and SPA’s in general, must have a different authentication structure.
SPA’s send authentication data to server for validation. This is where we store our persistent data on a RESTful API. The server, in SPA, sends back a token, not a session. The token is a JS object encoded as JSON. This token is stored in localStorage.
Then, when we request a protected resource, change password for example, we pass along the JSON token with the request to be evaluated by the server. The token is created by the server and then passed back to the server to verify that it is indeed the token that was created. We can’t create a token ourselves, only tokens created by the server can be used with the server.
Testing Your React APP
Testing your app isn’t just clicking around, you already do that a ton during development. Testing, in high livel computer science, is abstracted to it’s own field with it’s own methodologies. We are attempting to write code that tests the our applications.
Testing
Testing is the creation of automated test. The typical process is:
- Write your app
- test in browser manually
- automated testing
- ship app to server
Automated tests run automatically and test a tiny fraction of the app. This is called a unit test. This helps us find errors deep into the programming logic.
Also an idea of test-driven development. You write tests before writing application code, then write your code to satisfy your tests step by step
We do unit testing because there can be interaction effects between different components and their features, so we need to test the application as it grows.
Testing tools
You’ll need two tools to write good react tests.
- Test Runner – Responsible for running the test and providing validation library
- unit tests don’t run on the browser but rather an emulator
- Jest will be our test runner as it is the default React test enviornment
- Testing Utilities – This is the emulator that simulates the React App in how it mounts components and creates the DOM tree.
- React Test Utils is the default testing utility package
- Enzyme is a tool developed by Air-BNB and is recommended to testing
What to Test
Writing good tests is quite complex and requires practice. Rather than learn what to test, lets first look at what we want to avoid:
- DO NOT test the library, React, or 3rd party tools
- DO NOT test complex connections
Here is what you test:
- Test isolated units
- Test conditional outputs (what happens if properties change in your components)
Writing Good Tests
You can write 100 tests but not test the critical variable you need to. Conversely, you can test everything you need with 1 simple test if well designed. Testing is difficult and you will only get better with practice.
Learn how to test and think in test environments. Also learn the different methods provided by Enzyme and Jest to expand your testing vocabulary.
When writing tests, look at components and think about what crucial changes occur depending on external influences. Test for these factors.
Deploying React Apps
You’ve worked hard on the design and programming of your application, now all that is left is to place it on a web server so the world can witness your greatness. Fantastic job!
Deploying your app on the web is super simple and involves only a few steps:
- Adjust Basepath
- important when using React Router and serving your app from any folder other than the base folder. If you are using example.com/my-app/ then you need to set the <BrowserRouter basename=”/my-app/”>
- Build and Optimize Project
- Do this entire step with one convenient process: npm run build inside the create-react-app project folder
- Server must ALWAYS serve index.html (also for 404 cases)
- Often times, Routes might be dynamic so they are not set directly on the server. Upon receiving the request, the server might not have a specific file to return for that route. However, the app itself can identify that route and return data associated with it, all unbeknownst to the server. To protect this, make sure your server returns index.html for 404’s (not found errors)
- Upload Build Artifacts to Webserver
- Server doesn’t need to run anything extravagant, you only need a static server for the HTML, CSS, and lots of JS. AWS, GitHub, Firebase, they all provide static file servers that can meet your needs!
- Only upload files in /build folder
That’s all it takes to get your pages to the internet. Make sure you follow the command line instructions closely and change things as necessary for your hosting setup. Now you have a web address you can use to interact with your application on the web!