React is something every front-end developer should have in their tool belt. Some new concepts need to be learned, and a few things we used to apply in traditional MVP apps need to be unlearned. That's why I reached out to you to share knowledge and offer the best tips from some top React developers and engineers. Let's get started!
- How to deal with
this
Reference inside the promise?
While working with React.js, chances are you've faced a problem with how to access this
from inside the promise. For example, as exhibited in the code below, one of the problems could be this
is resolving inside the promise as undefined
:
class Component extends React.Component {
componentDidMount() {
axios.get('http://…').then(function(data) {
this.setState( { name: data.blah } );
});
}
}
There's more than one solution to determine this reference inside the promise. The earlier approach would be setting the self = this
reference. While this would work, the recommended solution, which is more incline with ES6, would be to use an arrow function here:
class Component extends React.Component {
componentDidMount() {
let component = this;
axios.get('http://…').then(function(data) {
component.setState( { name: data.blah } );
});
}
}
The arrow syntax, as described above, is a much reliable way to allow a user of this
to make reference to React.Component
classes, as we can analyze below:
class Component extends React.Component {
componentDidMount() {
axios.get('http://…').then(data => {
this.setState( { name: data.blah } );
});
}
}
Kindly note that instead of using function(data) { //body }
, we used data => { //body }
, and in this cases, this
reference won't get the promise instance back.
2) How to use rc-chartjs
or react-chartjs
in React.js Application running Under webpack-dev-server
?
webpack-dev-server
with hot reloading support. Individually, for this, I'm using a series of components that can b accessed in a React Transform Boilerplate.After you've hot reloading working rightly, you may end up facing issues with some JavaScript references inside third-party React.js components, like react-chartjs
component highlighted above in the title. In this particular case, most probably react-chartjs
, and its fork rc-chartjs
, have a similar kind of problem: they can't reach a reference to a window
object when scripts is bundled by webpack
and served by webpack-dev-server
.
To fix this, I used the import-loader provided by Webpack. Look at the …. Configuration example below:
module: {
loaders: [
{test: require.resolve('chart.js'), loader: 'imports?this=>window'},
]
}
As you can see, we're injecting this
reference to a window
object straight into chart.js
library.
3) How to use dependency injection in React.js application?
As JavaScript developers, dependency injection is one of the finest software design practices that we have at our disposal. By using dependency, we can avoid multiple duplicated code in the application, largely regarding services initialization and configuration. In the example below, I made use of a dependency injection library called Jimple to handle the injection of my service layer code into the components. But first, I need to ensure the Jimple container is injected rightly on each React.js component.
Let's have a look first on container description:
import Jimple from 'jimple';import { UsersService } from './services/UsersService';export let container = new Jimple();container.set('API_URL', function © {
return 'http://localhost:8080/api';
});container.set('API_VERSION', function © {
return '1.0.0';
});container.set('USERS_SERVICE', function © {
return new UsersService(c.get('API_URL'), c.get('API_VERSION'));
});
Next, on the Router
component we need to inject the container on each Component
rendered by its routes. For this, we defined a function named as createElement
which allows us to advance the container to component as a property:
import { Router, IndexRedirect, Route, History } from 'react-router';import { container } from './container';class MoneyApp extends React.Component {
render() {
return {this.props.children}
}
}// Pass container as prop to children components
function createElement(Component, props) {
return
}render((
),
document.getElementById('app'));
In the end, we can retrieve the dependencies as we will do in the example below:
class Overview extends React.Component {
constructor() {
super();
this.state = { pending: [], lastMonths: [] }
}
componentDidMount() {
let service = this.props.container.get('SERVICE');
service.yourMethod();
}
render() {
return Some content
}
}
4) Avoid className and Style in your components
If you want your application to have to consistent look and feel, you don't want to pass around classNames
and styles in an ad-hoc manner. Keeping the possibility to pass any style or className
to a component means that:
- You've to consider what style it requires to make it look the way you want.
- You've to understand the default set of styles, in order to know the styles from the beginning point.
- You can pass any kind of styles that don't make sense and may interrupt your UI.
Let's see what I'm talking about with some examples.
Let's render a 'primary' button to start.
In the above example, we've to know that we need to pass the classes btn-primary
. Also, we could pass any other className
that would not make wisdom, like make-this-look-like-a-pig
.
Instead, consider the following code snippet:
In the code pattern above, we use a custom Button component that internally may use the initial approach but just exposes a primary
Boolean property like this:
class Button extends React.Component {
render() {
// Using https://github.com/JedWatson/classnames
var className = classNames('btn', this.props.primary && 'btn-primary');
return ;
}
}
Let's consider another example. We want to render the principal content on the left, and the sidebar on the right:
Main content
Sidebar content
What if we want to use flexbox? We need to come here and modify the styles we're passing to the div. Moreover, we can pass any other style that we want, including styles that do not make any sense or that we don't intend someone to use.
Now instead, take a look at the following code:
Main content
Sidebar content
We encased that piece of the layout into different components, which hide that style implementation detail away from us, and we simply use them. This specific piece of code doesn't even care if the sidebar is on the right or on the left.
One more example, exhibiting a successful notification:
A good notification
Same issue as the first example. We need to know that those classes need to be implemented.
A good notification
Using a custom notification component that takes a type, and which can be validated via React.PropTypes to just be any value of a predefined set makes the user of this component not need to rethink of any class convention.
One final example. Let's consider how we could simplify layouting a form by defining a Layout
Component that postulates the width of its children.
Here we first layout three inputs in a similar row, where the first two have equal size, and the third one is half of the size of the others, with the row taking the whole width of the container. Then we render another row with a button taking full width.
Please consider how avoiding styles and classNames
forces you to distinguish styling concerns like how it looks vs. how it lays out, which suggests you'll have different components to enforce each. In the last example, the Input
and Buttons
have no clue how they will lay out. That's the job for a parent component.
Think about components' properties as their API. Exposing classNames
or styles is like exposing an 'options' object which can have hundreds of routes. Do you really think that for your own components? Do you actually want to think about every possible option when you use them?
It will be good to leave styles and className
to be used in leaf-most components and create a set of components that will build look and feel, and another set that will define layout.
When you execute this, it will become much simpler to generate new components, pages, and views of your app, since you'll only need to arrange your set of appearance and layout of components and pass them the right props without even anticipating about CSS or styles.
If you want to tweak the styles or modify the look and feel of your application as an added benefit, you will just need to change the library components. Also, if you keep the identical API for them, the components that use them will remain untouched.
5. Create tiny components that just do One Thing
Generate small components that halt particular parts of your page or add specific new behavior to your UI. You'll be able to consider each piece individually, and you will even be able to benefit from performance optimization like shouldComponentUpdate
in a more granular manner, or other lifecycle components.
Moreover, they will become more reusable across your application. Not to indicate to the React community, if they're generic enough.
A few hints to know if you separate your component:
- Keep your render function short and simple. You can split the render function into various functions in a similar component, but if it makes sense, try splitting those render chunks into separate components.
- Are you working with application state logic and also a presentation in the same component? Attempt to separate it into a component that just handles the state and one or several components that handle the presentation, where the state is passed as a property to the child components.
- Do you have some elements in your render method that require to be updated much more frequently than others? Extract that chunk into a separate component, and try to localize the state updates inside (if it makes sense), or use
shouldComponentUpdate
in the other components to prevent any unnecessary re-renders. - Do you have a form with various sections and fields but you really don't care about all the intermediate state, Extract that form into its own component (or even varying sections of the form into their own components) that accept the primary values as properties, and have an
onSubmit
callback property that's called with end values of the form, making the parent not need to re-render every time an intermediate change in the form occurs. Internally in those section components, either uses uncontrolled components or implement the component internal state. - Are you doing a lot of styling for layouting a set of components? Exact that into layout components that have configurable yet predefined layouts and place your components as children of them.
- Are you adding behavior to some component through the state like collapsing, expanding, hovering, or making it pop over? Move that behavior into separate components that take a single child which is a function to render, and sets the state via patterns to that function, like:
{hovered => {hovered ? "I'm hovered!" : "I'm not hovered"}}
Conclusion
There are precisely several reasons to split your current component into more. Remember, components in React are quite like functions. You can split a function into many. Also, you can compose or combine them in any way you want, and still get the same result.
For coronavirus updates, you can visit CNBC Live Stream.
Share & Manage Reusable React Components with Bit
Use Bit (Github) to share, document, and manage reusable components from different projects. It's a great way to increase code reuse, speed up development, and build apps that scale.