Stateless Functional Components

by kirupa   |   filed under Learning React

Let's face it. The components we will be writing aren't going to be changing the world. The bulk of the components we are going to write will do a few simple things, all of which revolve around taking some props and spitting out some markup. For these simple components, is all the complexity we have to deal with when defining them necessary? Probably not.

In the following sections, we are going to look at a greatly simplified syntax for defining components that should look very familiar to you.

Onwards!

OMG! A React Book Written by Kirupa?!!

To kick your React skills up a few notches, everything you see here and more (with all its casual clarity!) is available in both paperback and digital editions.

BUY ON AMAZON

Getting Back to Functions

The syntax we have been using so far for defining components has looked as follows:

class LightningCounter extends React.Component {
  constructor(props) {
    super(props);
 
    this.state = {
      strikes: 0
    };
 
    this.timerTick = this.timerTick.bind(this);
  }
 
  timerTick() {
    this.setState({
      strikes: this.state.strikes + 100
    });
  }
 
  componentDidMount() {
    setInterval(this.timerTick, 1000);
  }
 
  render() {
    var counterStyle = {
      color: "#66FFFF",
      fontSize: 50
    };
 
    var count = this.state.strikes.toLocaleString();
 
    return (
      <h1 style={counterStyle}>{count}</h1>
    );
  }
}

This syntax is not terrible. It is great for allowing you to define complex stateful components that define large parts of our app logic. For doing all of that, you need the full power classes provide. You want to extend the Component base class to have access to the state API, lifecycle methods, and other React features. Now, here is a wrinkle. What if your component doesn’t do a whole lot? What if your component will be purely presentational where it just takes some props and spits out some JSX kinda like the following?

class SimpleMessage extends React.Component {
    return (
      <p>Message is: {this.props.message}</p>;
    );
  }
}

For the many components you create that fall under this bucket, you can define a component as just a plain old function:

function SimpleMessage(props) {
  return <p>Message is: {props.message}!</p>;
}

Defining these functional components or stateless functional components looks ridiculously simple, and it totally works. Behind the scenes, when using this syntax, React still creates a proper component with all the hooks in all the right places. The way you call this component doesn't change either. Here is the ReactDOM.render call for our SimpleMessage component:

ReactDOM.render(
  <div>
    <SimpleMessage message="Functions are back in style!"/>
  </div>,
  document.querySelector("#container")
);

What you can't do with this approach are things like using lifecycle methods, initializing default values in a constructor, defining state, and performing other tasks that are only suited for the formal structure of the class based approach.

Stateless Functional Components and their Arguments

In this function-based world, the props object is passed in as the first argument:

function HelloSomething(props) {
  return <p>Hello, {props.target}!</p>;
}

This shouldn't be a total surprise, for we've already seen that in the snippets earlier. One detail to note is that you can set any name you want to refer to the first argument. It doesn't have to be props like we've seen so far. It can be something like jello:

function HelloSomething(jello) {
  return <p>Hello, {jello.target}!</p>;
}

In more advanced (and possibly rare) cases, you may need to access the context object from inside your component. You can do that using this function-based approach easily, for the context object is passed in as the second argument:

function HelloSomething(props, context) {
  return <p>Hello, {props.target}!</p>;
}

Just like with our props, you can set this argument's name to whatever you like as well.

Kicking it up a Notch!

With this syntax, because you are working with functions, you can go a little crazy and take advantage of newish JavaScript techniques you have at your disposal. For example, if you are someone who finds the existence of the function keyword and return statement to be offensive, you can go even more compact and use arrow functions:

var SimpleMessage = (props) => <p>Message is: {props.message}!</p>;

The end result is the same. But why stop here? If you are not a fan of having to rely on your props object each time you want to access a property on it, you can take advantage of destructuring:

var SimpleMessage = ({ message }) => <p>Message is: {message}!</p>;

I am sure there is more dark magic you can invoke to make our component definition even more compact, but you get the idea. Functions give you a lot more flexibility than the more structured class based approach when it comes to using the latest EcmaScript features.

Conclusion

Everything I have shown you here is entirely optional. If you like defining all your components using the class syntax, you can totally do so. You won't be negatively impacted - at least not now. This is a subtle detail to keep in mind, for the React team has stated they may optimize components created using the function-based syntax. I don't think they've done too much yet, but that could change at any point.

Lastly, even if you never decide to define stateless functional components, you should familiarize yourself with them and some of the variations we've seen. Many examples you will see in the wild may use this syntax extensively, so you need to know how to work with them and not get tripped up. This has been a public service announcement.

If you have a question about this or any other topic, the easiest thing is to drop by our forums where a bunch of the friendliest people you'll ever run into will be happy to help you out!

THE KIRUPA NEWSLETTER

Get cool tips, tricks, selfies, and more...personally hand-delivered to your inbox!

( View past issues for an idea of what you've been missing out on all this time! )

GOT A QUESTION?

HOT FORUM TOPICS

Serving you freshly baked content since 1998!

Killer hosting by (mt) mediatemple

Facebook Twitter Youtube Pinterest Instagram Github
BACK TO TOP
new books - yay!!!