How to avoid refactoring in your first React.js application

How to avoid refactoring in your first React.js application

Popularity of React.js is growing pretty fast and it seems like React became a compact and beautiful way of how to develop your applications. I have worked on a side project and felt like it is right time to try React. During development of my first project in React I had to do several refactorings. In this short blog post I will try to point out some pitfalls, which you should take care of if you want to avoid refactoring in your first React.js application.

The Begging

Over the internet you can find a lot of tutorials how to start with React.js with basic examples. I recommend Ken Wheeler’s article Learning React.js: Getting Started and Concepts and Chris Harrington’s article React Tutorial: Creating a Simple Application Using React JS and Flux Architecture.

Props vs State

After reading some introductions to React you probably noticed components properties props and state. When I developed my first React application I didn’t pay attention to these properties and thought it’s clear to me. I underestimated the potential issues of not using them properly. Later, I realised that I used these properties in the wrong way. By misusing these properties you can end up with a lot of bugs, which will cost you a lot of time to fix. If you know the difference between state and props and are not sure which one to use in your component, read this article. I like especially the decision table and after couple of times using this table, you can easily keep them in mind and avoid misusing these properties.

props state
Can get initial value from parent Component? Yes Yes
Can be changed by parent Component? Yes No
Can set default values inside Component?* Yes Yes
Can change inside Component? No Yes
Can set initial value for child Components? Yes Yes
Can change in child Components? Yes No
Source: https://github.com/uberVU/react-guide/blob/master/props-vs-state.md#changing-props-and-state

Try to keep as many of your components as possible stateless. Dan Abramov wrote great article about separation Presentational and Container Components. In React.js documentation we can find:

A common pattern is to create several stateless components that just render data, and have a stateful component above them in the hierarchy that passes its state to its children via props. The stateful component encapsulates all of the interaction logic, while the stateless components take care of rendering data in a declarative way.

Lifecycle methods

React components have their own lifecycle which executes a sequence of various methods. Lifecycle methods are different, when component is mounted and updated, you can see lifecycles and sequence of methods in this table, which is more readable than list of methods in documentation.

Anti-patterns and best practices

When I play with a new technology I always try to find some anti-pattern and best practices. When I started with React, I found only one anti-pattern. In terms of best practices I like John Cobb’s An opinionated guide to React.js best practices and conventions and Jan Carlo Viray’s article React Best Practice Compilation. From the beginning, try to organize application file structure. Recently, I read React.js Best Practices for 2016 and highly recommend it.

ES6

When I developed my first React.js components, I followed some tutorials and used ES5 syntax. You can define React component as an ES6 class and use Babel for transpilation your code to ES5. In the beginning I didn’t have any experience with Babel and wasn’t sure if transpilation works correctly. I decided to try ES6 syntax and Babel, because I wanted to have my source code cleaner, more readable and quicker to develop. Since I tried it, I can’t imagine writing my code in ES5. ES6 provides so many great features, your code is more readable, you can develop more effectively and Babel works very well. Thus, I don’t see any reasons why not using ES6. If you want to refactor your components, follow steps of Kris Jordan’s article Refactoring React Components to ES6 Classes and some others tips you can find here. If you really need mixins in your component, just use react-mixin.

shouldComponentUpdate()

React’s diff algorithm between virtual DOM and actual DOM is innovation which boosts the performance of your application and some other frameworks try to follow. If performance of your first React.js application is a critical aspect, you should consider using this method and immutable data structure for React components. This method is triggered before the re-rendering process of component giving the developer the ability not to perform render method and diffing algorithm. If you use immutable data structure, it makes tracking changes cheap and “previous” props and stats can be compared with the new one. I recommend Tomas Weiss’s article Turbocharge Your React Application with shouldComponentUpdate and Immutable.js, where you can find result of basic benchmark with and without shouldComponentUpdate method.

There are more use cases, when this method is very handy. Let’s imagine we need a big grid component, which does some complex things with cells. For our grid component we find only jQuery library and their extensions. Problem solved, we decide to use this library, otherwise we spend long time to rewrite this library with extensions to React. If we want to change the data of our big grid component, we have to re-initialize our grid as a jQuery object in React using the componentDidUpdate method. If our jQuery library provides a method $(gridObj).updateCellOnCoordinates(x, y, data); to update a particular cell instead of a whole grid and we use immutable data structure, in the shouldComponentUpdate method we can just diff data for our jQuery object and use the updateCellOnCoordinates method without re-initializing jQuery object in the componentDidUpdate method.

let diff = require('immutablediff');
shouldComponentUpdate(nextProps, nextState) {
let propsDiff = diff(this.props.data, nextProps.data);
if (propsDiff.size === 1) {
let operation = propsDiff.get(0).get("op");
let replacedObj = propsDiff.get(0).get("value");
switch (operation) {
case "replace":
if (Immutable.Map.isMap(replacedObj)) {
let editedObj = {};
let xCoordinate;
let yCoordinate;
for (let entry of replacedObj.entries()) {
if (entry[0] === 'x-coordinate'){
xCoordinate = entry[1];
}
if (entry[0] === 'y-coordinate'){
yCoordinate = entry[1];
}
editedObj[entry[0]] = entry[1];
}
$(ReactDOM.findDOMNode(this.refs.dataGrid))
.updateCellOnCoordinate(xCoordinate, yCoordinate, editedObj);
return false;
}
break;
case "remove":
break;
case "add":
break;
default:
return true;
}
}
return true;
}
view raw DataGrid.jsx hosted with ❤ by GitHub
We just diff data props of a React component and re-initialize a cell of jQuery object without re-initializing jQuery grid object with other plugins in the componentDidUpdate method (and without re-rendering the whole React component).

Conclusion

In this article I wanted to point out pitfalls and how to avoid them if you are going to develop your first react application. The most important thing is not to misusing state and props. With ES6 and Babel you can develop faster and cleaner code. If you are sure your application will re-render thousands of components or you are going to use a library, which complex objects have to be re-initialized in componentDidUpdate method, consider using immutable data structure of your store along with the shouldComponentUpdate method.

NEED A FULL STACK WEB DEVELOPER? LET'S BUILD SOMETHING.

GET IN TOUCH
1 COMMENT
  • How to avoid refactoring in your first React.js application – ReactJS News
    Reply

    […] How to avoid refactoring in your first React.js application […]

Leave a Reply

Your email address will not be published. Required fields are marked *

%d bloggers like this: