Grokking React Native
Vote

0% completed

​

Functional and Class Components

What the Class Needs

How React Uses Each One

Both Forms Can Hold Changing Data

Comparing the Two

Which One to Use

The same greeting can be written in two ways, and both put identical elements on the screen. One way uses a JavaScript function, and the other uses a JavaScript class. The first form is called a function component, which many articles also call a functional component, and the second is called a class component.

import { Text, View } from 'react-native'; function Greeting({ name }) { return ( <View> <Text>Hello, {name}!</Text> </View> ); } export default Greeting;
import { Component } from 'react'; import { Text, View } from 'react-native'; class Greeting extends Component { render() { return ( <View> <Text>Hello, {this.props.name}!</Text> </View> ); } } export default Greeting;

We rendered both with the name Maya and compared the results, and the two trees were the same:

View Text: Hello, Maya!

This is a second way of sorting components, separate from the built-in and custom groups in the previous lesson. That earlier question asks who wrote the component. This one asks how a custom component is written.

What the Class Needs

The class version has three requirements that the function does not have. It must extend Component, which comes from React, and older code often writes the same thing as React.Component. It must define a method named render, and it reads its values from this.props.

The render method is not optional. We wrote an empty class named NoRender. It failed as soon as React tried to display it, and React reported the cause first:

No `render` method found on the NoRender instance: you may have forgotten to define `render`. TypeError: instance.render is not a function

How React Uses Each One

The two forms also differ in what React does with them. To see the order, we added a console.log to each form and had a parent render it with the name Maya and then with the name Omar.

function GreetingFunction({ name }) { console.log(`function called, name=${name}`); return <Text>Hello, {name}!</Text>; } class GreetingClass extends Component { constructor(props) { super(props); console.log(`constructor called, name=${props.name}`); } render() { console.log(`render called, name=${this.props.name}`); return <Text>Hello, {this.props.name}!</Text>; } }

The console showed this:

function called, name=Maya function called, name=Omar constructor called, name=Maya render called, name=Maya render called, name=Omar

React calls a function component each time it needs the UI. For a class component, it creates one object the first time, then calls render on that same object each time.

React calls a function component on every render, while it creates one class instance and calls its render method on every render.
React calls a function component on every render, while it creates one class instance and calls its render method on every render.

Follow the name Omar in each column. In both forms it produces one new call, so the constructor runs only once, at the very start.

Both Forms Can Hold Changing Data

You may read that function components are only for static content and that classes are needed when data changes. That was true of old versions of React, and it is no longer true. A function can keep data between renders through useState, a function from React that the Hooks and State chapters explain. For now, read it as "a value that React remembers, plus a function that changes it".

import { useState } from 'react'; import { View, Text, Button } from 'react-native'; function TapCounter() { const [taps, setTaps] = useState(0); return ( <View> <Text>Taps: {taps}</Text> <Button title="Tap" onPress={() => setTaps(taps + 1)} /> </View> ); } export default TapCounter;

Here is the same counter as a class, which is what you will see in older projects:

import { Component } from 'react'; import { View, Text, Button } from 'react-native'; class TapCounter extends Component { state = { taps: 0 }; render() { return ( <View> <Text>Taps: {this.state.taps}</Text> <Button title="Tap" onPress={() => this.setState({ taps: this.state.taps + 1 })} /> </View> ); } } export default TapCounter;

We ran both and pressed the button twice in each. Both showed Taps: 2, so they behave the same way.

Comparing the Two

Function componentClass component
Written asA function that returns JSXA class that extends Component
Returns UI fromThe function bodyThe render method, which is required
Reads its values fromThe function's parameterthis.props
Keeps changing data withuseStatethis.state and this.setState

Which One to Use

Write function components. The React documentation recommends defining components as functions, and it does not recommend classes for new code. The function is shorter, and everything in the rest of this course that keeps data or reacts to changes uses functions.

Class components are still supported, so existing class code keeps working, and you need to read them when you work on an older project. There is also one case where a class is still required. An error boundary, a component that catches a rendering error in its children and shows a fallback screen, cannot currently be written as a function. Even then, you do not have to write the class yourself, because the react-error-boundary package provides one.

class ErrorBoundary extends Component { state = { failed: false }; static getDerivedStateFromError() { return { failed: true }; } render() { return this.state.failed ? <Text>Something went wrong.</Text> : this.props.children; } }

When a child of this class threw an error in our test, the screen showed Something went wrong. instead of crashing. You do not need this yet, and it is here only as the one exception to the rule.

Reading Progress

0%


Vote for new content

On This Page

What the Class Needs

How React Uses Each One

Both Forms Can Hold Changing Data

Comparing the Two

Which One to Use