Author avatar

Raphael Alampay

Wrap a Custom React.js Component for an HTML Button

Raphael Alampay

  • Oct 22, 2020
  • 5 Min read
  • 181 Views
  • Oct 22, 2020
  • 5 Min read
  • 181 Views
Web Development
Front End Web Development
Client-side Frameworks
React

Introduction

React.js allows developers to extend the default functionality of an HTML input element by creating a component around it. This gives the input element more custom functionality, behavior, and even values that it can maintain on its own. In this guide, we'll be taking a look at creating a custom component for an HTML button and extending its functionality other than attaching an event handler for its onClick attribute.

Setup

Suppose that you want to create a button that does the following:

  1. Changes the color to red if it's unclickable
  2. Changes the color to green if it's clickable
  3. Changes the text of the button to "Loading..." if it's unclickable

This would be quite tedious if it were done manually. You'd probably have several JavaScript routines that would modify its behavior or several CSS files that might change how it looks depending on the classes added or removed by JavaScript. This is all good if you're doing it for a single button. However, if you expand to something like an array of buttons generated by a backend process, it tends to get messy to maintain.

To solve this, create a component representing that button, which you can call MyCustomButton:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import React from 'react';

export default class MyCustomButton extends React.Component {
  constructor(props) {
    this.state = {
      text: "Click Me"
    }
  }

  render() {
    return (
      <button>
        {this.state.text}
      </button>
    );
  }
}
javascript

Nothing special here. You start off by creating a component that maintains a text value in its state and renders the actual HTML button. The value of text becomes the actual text rendered for the button as called by this.state.text.

Changing Color to Red or Green

Next, you'd want to indicate if the button is clickable or not by changing its background color to red in the case of it being unclickable. This means that the disabled state of the button is set to true. When solving this type of problem in React.js, always remember to have everything managed by the component and just have values trigger the properties of that component via props, which is initially passed to the constructor. You can assume that props can have a property called disabled that can optionally be passed by an external component calling this MyCustomButton component. However, since it is optional, you want to have a default value for it. To do this, create a temporary variable called disabled that accesses this.props.disabled from within render():

1
var disabled = this.props.disabled || false;
javascript

The || indicates that if this.props.disabled is null, then it takes an initial value of false. Hook the value up to the actual disabled property of the HTML button:

1
2
3
<button disabled={disabled}>
  {this.state.text}
</button>
jsx

Next, you can style the button by passing an object to its style attribute. Just like disabled, you can temporarily declare another variable to change the backgroundColor property of the object to red:

1
var style = { backgroundColor: 'red' };
javascript

However, if disabled is false, then the backgroundColor should be green:

1
2
3
if(disabled == false) {
  style = { backgroundColor: 'green' }
}
javascript

Hook the variable style to the attribute style of the rendered HTML button:

1
2
3
<button disabled={disabled} style={style}>
  {this.state.text}
</button>
jsx

Dealing with Text

To change the text of the button to "Loading...", you can use the same technique as in the previous section. Create a temporary variable text and set it to "Loading..." depending on the value of disabled:

1
2
3
4
5
var text = this.state.text;

if(disabled) {
  text = "Loading...";
}
javascript

Replace the original rendered this.state.text to simply text within the jsx. Your rendered button should now look like the following:

1
2
3
<button disabled={disabled} style={style}>
  {text}
</button>
jsx

Overall Code

Your overall code should now look like the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import React from 'react';

export default class MyCustomButton extends React.Component {
  constructor(props) {
    this.state = {
      text: "Click Me"
    }
  }

  render() {
    var style = { backgroundColor: 'red' };

    if(disabled == false) {
      style = { backgroundColor: 'green' }
    }

    var text = this.state.text;

    if(disabled) {
      text = "Loading...";
    }

    return (
      <button disabled={disabled} style={style}>
        {text}
      </button>
    );
  }
}
javascript

Conclusion

Instead of using a normal HTML button and having to maintain all sorts of behavior through external code, you can create a custom React.js component as a wrapper for that element with additional functionality. This is especially useful if you want to share common behavior for a dynamically generated set of UI components that are rendered by your app's own logic. Using React.js' passing of values to props, you can control the behavior of the custom component accordingly and even set default values for it so as not to burden external code to put in initial values.

As an extra step, try to see if you can make the "Click Me" text a default value if an external component fails to pass a value for the props property called buttonText (Hint: Is state a good place to store text in this scenario, or can you get away with simply using props)?

0