Reusable Components in React — A Practical Guide

September 27, 2018 0 Comments

Reusable Components in React — A Practical Guide

 

 

Normally in vanilla JavaScript, when you want to re-use some code, you write it as a function. In React, however, you write your code as a component. We can simply create a class and then place multiple instances of that class wherever we want.

While this sounds like the easy thing to do, in some cases it can cause some headache when you want to go back and make minor changes to the behavior.

In this post, I will show how to create a simple reusable React component. I will also go through some of the best practices that I think can help build better components in React.

Tip: Bit is a useful way for reusing React components across different projects, and create a shared catalog for your team to collaborate on. Different team members can easily share, develop and use your components anywhere.

First, I will create a new React Project using the create-react-app command:

create-react-app my-app

Once the project is created. Go to the App.js file and change the existing code with this snippet:

Here, there is a <div> element that has some text inside it. If I want to replicate it, I will have to write the same div element again. What we can instead do is extract the div element inside a variable, and write that element directly in my app’s JSX.

If you run yarn start command, you will see that the app renders the text the same way in both cases.

What if I want to render some other kind of text? Or if I want to render two different texts?

To do so, I am going to make some changes to the helloWorld variable.

First, I have renamed the variable as message. I am then passing props as an argument to this variable. Note that I am using ES6 arrow function to do this.

props is an object that has a msg property in it. Inside the App component, I am replacing the {helloWorld} with {message}. Inside this message variable, I am defining the msg prop with some text.

I’ve now created a simple, re-usable React component. I have taken some JSX, wrapped it inside a function, and made a function call to render some text.

But function calls don’t really compose as well as JSX does. It would be better to turn these function calls into JSX. So let’s start out with React.createElement and see how we can convert into JSX. A great thing about React.createElement is that can take a string and a function to indicate what element we want to render.

It will pass the props to the function, and that function presumably will some more elements. Here, the message function is rendering a <div>.

But this looks way too complicated. Let’s simplify things like this:

Here, I am changing my message function to Message, changing the function into a component. By doing so, I can use it as a self-closing element inside the App component as shown in the above code snippet.

If I change the msg prop to children prop, React will still render the exact same thing. I can even put one Message element inside another Messageelement.

class App extends Component {
render() {
return (
<Message>
Hello World
<Message>Reusable Components</Message>
</Message>
);
}
}

So, to create a re-usable component in React, all you need to do is create a function that has a capital letter as its first character. This function should receive props as an argument and you can use these props in whatever it is that you want your re-usable component to return.

If your component’s sole purpose is to just display some data, then I would suggest you to write that component as a functional component instead of a class component.

Here’s how a typical class component that can be converted into a functional component would look:

class Hero extends React.Component {
render() {
return (
<div>This could've been a functional component</div>
)
}
}

Converting this component into a functional one, we get:

const Hero = () => <div>Functional Components are so simple!</div>

Both of these snippets are defining the same Hero component. The only difference is that the second method is shorter and simpler. By using functional components, we can even forget about using this to access any props inside the JSX template.

Make sure that you use functional components in certain situations only. One such situation is when your component is only displaying some data.

React has this annoying requirement for a single parent element inside the component.

class Login extends React.Component {
render() {
return (
<input name="login"/>
<input name="password"/>
)
}
}

This is throw an error. To solve this issue, we can add a simple <div> element in there code first like this:

class Login extends React.Component {
render() {
return (
<div>
<input name="login"/>
<input name="password"/>
</div>
)
}
}

But now, React 16 has provided us with a new syntax called Fragments. Fragments allow us to replace the useless parent div element with a React.Fragment.

class Login extends React.Component {
render() {
return (
<React.Fragment>
<input name="login"/>
<input name="password"/>
</React.Fragment>
)
}
}

But this can be considered to be worse than writing div. So React has provided us with this short hand syntax for Fragment as well.

class Login extends React.Component {
render() {
return (
<>
<input name="login"/>
<input name="password"/>
</>
)
}
}

State plays an important role in any React application, and hence it is very important that developers are careful when they are working with it.

The initial step of writing state are quite simple, we create a constructor method inside the class’s render and initialize the state inside it.

Then, when you want the app to update the state, you use the setState method.

One thing we need to avoid doing is using this.state and this.props inside the setState method like this:

this.setState({ name: this.state.name, name});

What we can do instead is keep the same state as before, and add only the new name property to our state.

this.setState({...this.state, name});

Why is this so important? That’s because the setState is asynchronous in nature, as the updates to our state are batched to optimize the DOM manipulations.

In React, the HTML form elements work a little bit differently from other DOM elements. This is because unlike other DOM elements, form elements keep some internal state. For example, this form in plain HTML accepts a single name:

<form>
<label>
Name:
<input type="text" name="name" />
</label>
<input type="submit" value="Submit" />
</form>

This form has the default HTML form behavior of navigating to a new page when the user submits the form. If you want this behavior in React, it just works. But in most cases, it’s convenient to have a JavaScript function that handles the submission of the form and has access to the data that the user entered into the form. The standard way to achieve this is with a technique called “controlled components”.

The alternative to controlled components, is called uncontrolled components! Uncontrolled components is a method where form data is handled by the DOM itself.

In HTML, form elements such as <input>, <textarea>, and <select> typically maintain their own state and update it based on user input. In React, mutable state is typically kept in the state property of components, and only updated with setState().

We can combine the two by making the React state be the “single source of truth”. Then the React component that renders a form also controls what happens in that form on subsequent user input. An input form element whose value is controlled by React in this way is called a “controlled component”.

class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};

this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}

handleChange(event) {
this.setState({value: event.target.value});
}

handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}

render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}

To write an uncontrolled component, instead of writing an event handler for every state update, you can use a ref to get form values from the DOM.

class NameForm extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.input = React.createRef();
}

handleSubmit(event) {
alert('A name was submitted: ' + this.input.current.value);
event.preventDefault();
}

render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" ref={this.input} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}

Click on the links below to know more about controlled and uncontrolled components:

As I mentioned before, React Components are a great way of writing reusable code. We can simply create a class and then just call its instances wherever we want. Still, there are a few cases that can leave developers searching for a better option. Some of these cases are:

  • Its not entirely your code — Developers rarely work alone. They work in groups, sharing their on platforms like GitHub and Bit. So, the reusable component that you might be using in your app, might not be written by yourself. And that will stop you from tinkering with it, because you don’t want to generate numerous bugs which will take you even longer to fix.
  • Here, but not there — You might also want to be selective about some of the behaviors of the reusable component. Meaning, you want it to render at some places with only certain behaviors enabled. So you can’t change the original component because then all the instances of the component will be changed. And if you decided to write a new component, then what’s the point of using reusable components anyways?


Tag cloud