Functional Components

A stateless component has no state variables. Stateless components never change state. Stateless components are also referred to as presentational or dumb components. Because they do not have any state variables, stateless components do not need to have a constructor() method.

Functional components:

The features listed above are shown in the code below:

// Class component

class DropDownRegionsList extends React.Component 
{
    constructor(props)
    {
        super(props) 
    }            
    
    
    render()
    {           
        return ( 
                <div>

                    {this.props.region}

                </div>               
        )
    }
}





// Functional component

const DropDownRegionsList = props =>
{        
    return ( 
            <div>

                {props.region} 

            </div>               
    )
}

In this countries example, the DropDownRegionsList component is stateless. Change the code so that this becomes a functional component, as shown here.

State

A hook is a function that allows us to access a React feature. Functional components use the useState() hook to allow the use of state variables. The useState() hook uses array destructering to associate a state variable with a function. The function is used to update the state variable. Each state variable will have its own useState() hook. The useState() hook allows us to set the state variable with an initial value. React ensures useState() is only called once for each functional component. React also ensures that the value saved in a state variable is preserved between calls to a functional component. The useState() hook syntax is shown below:

const [stateVariableName, functionName] = useState(initialValue)

 

useState() hooks replace the this.state variable that is used in class components. As there is no consturctor() method, useState() hooks are declared to be global to a functional component. Each state variable is assigned its own useState() hook, as shown below:

// Class component

class CountriesForm extends React.Component 
{
    constructor(props)
    {
        super(props)
        
        this.state = {selectedCountries:this.props.countries,
                      selectedRegion:"All Regions"}
    } 


    ... 

}



// Functional component

const CountriesForm = props => 
{
    const [selectedCountries, setSelectedCountries] = useState(props.countries) 
    const [selectedRegion, setSelectedRegion] = useState("All Regions")


    ...

}

 

State variables are global to all of the methods inside a functional component (just as the this.state variable is with class components). When using state variables in functional components, we do not need to include the this.state as part of the variable, as shown below:

// Class component

class CountriesForm extends React.Component 
{
    constructor(props)
    {
        super(props)
        
        this.state = {selectedCountries:this.props.countries,        
                      selectedRegion:"All Regions"}
    } 


    ... 


    render()
    {           
        return (  
            <div>
              <h1>{this.state.selectedRegion}</h1>                          
            </div>
        )
    }
}



// Functional component

const CountriesForm = props => 
{
    const [selectedCountries, setSelectedCountries] = useState(this.props.countries) 
    const [selectedRegion, setSelectedRegion] = useState("All Regions")


    ...


    return (  
        <div>
            <h1>{selectedRegion}</h1>                          
        </div>
    )
}

 

A state variable can be modified by calling its associated function. For example, in the code below , setSelectedRegion() is called to change the value of selectedRegion.

// Class component

class CountriesForm extends React.Component 
{
    constructor(props)
    {
        super(props)
        
        this.state = {selectedCountries:this.props.countries,        
                      selectedRegion:"All Regions"}
    } 


    handleRegionsChange = e => 
    {
        this.setState({selectedRegion: e.target.value})
		
        ...

    }

    ... 

}



// Functional component

const CountriesForm = props => 
{
    const [selectedCountries, setSelectedCountries] = useState(props.countries) 
    const [selectedRegion, setSelectedRegion] = useState("All Regions")


    handleRegionsChange = e => 
    {
        setSelectedRegion(e.target.value)
		
        ...

    }


    ...

}

useEffect()

The useEffect() hook allows functional components to access React lifecycle functions, such as componentDidMount() and getDerivedStateFromProps().

The useEffect() hook below will be called every time a functional component is called.

    useEffect(() => {
    
        ...

    })

 

 

The useEffect() method below will be called once. This one call will happen the first time that a functional component is called. This does the same role as the class component's ComponentDidMount() method.

    useEffect(() => {
    
        ...

    }, [])

 

 

The useEffect() method below will be called when props.countries has changed. This does the same role as the class component's GetDerivedStateFromProps() method.

    useEffect(() => {
    
        ...

   }, [props.countries])

Functional Component Web Apps

To convert a web app's class component into a functional component, we need to:

  1. Make the changes described above. In summary, these are:
    1. Replace the React Component inport with the useState imports, as shown below:
      REPLACE
      import React, {Component} from "react"
      
      
      WITH one of the lines of code below (depending on whether the Component has a state)
      import React, {useState} from "react"
      
      
      import React from "react"
      
    2. Replace each state variable in the this.state JSON variable with a useState() hook
    3. Replace componentDidMount() and getDerivedStateFromProps() with useEffect()
    4. Replace all instances of this.setState() with a call to the state variable's associated function that was declared using the useState() hook
    5. Remove the constructor() method
    6. Remove the render() method
    7. Remove all instances of this.state. from the code
    8. Replace all instances of this this.props with props in the code
  2. Export the component, as shown below:
    const MyComponent = props =>
    {
        ...
    }
    
    
    export default MyComponent 
  3. If the component has PropTypes, these need to be declared outside the functional component's scope, but in the same file, as shown below:
    const MyComponent = props =>
    {
        ...
    }
    
    
    MyComponent.propTypes = {
        name:PropTypes.string,
        age:PropTypes.number 
    }
    
    
    export default MyComponent 
  4. All of the functional component's methods need be declared as const, as shown below:
    const MyComponent = props =>
    {
        const handleHeaderClick = e =>
        {     
    
            ...
    
        }
    }
  5. When the render() method is removed, any code in the render() method that preceeds the return() should be left where it is, as shown below:
    // Class component
    
    const MyComponent = props =>
    {
    
        ...
    
    
        render()
        {
            const flag = `https://flagcdn.com/256x192/${(props.country.alpha2Code).toLowerCase()}.png`		
            return ( 
                
    ...
    ) } } // Functional component const MyComponent = props => { ... const flag = `https://flagcdn.com/256x192/${(props.country.alpha2Code).toLowerCase()}.png` return (
    ...
    ) }

Modify the login example so that it uses functional components, as shown here.

Modify the countries example so that it uses functional components, as shown here.

 
<div align="center"><a href="../versionC/index.html" title="DKIT Lecture notes homepage for Derek O&#39; Reilly, Dundalk Institute of Technology (DKIT), Dundalk, County Louth, Ireland. Copyright Derek O&#39; Reilly, DKIT." target="_parent" style='font-size:0;color:white;background-color:white'>&nbsp;</a></div>