In React, the class components and lifecycle methods have changed quite a bit in the last few years. Often times a developer may be handling legacy code and the newer paradigm of functional components and hooks. In this article I will use a basic example of converting a class component into a functional component with the hooks. Repo
The Rules Functional && Class Components
- props are read-only, the same props must return the same result. Components that respect their props are called “pure”.
- Do not mutate the state directly
The Functional vs Class:
Functional Component
- Takes advantage of functional programming
- A function with a traditional return statement
- Functional Components can be stateless
- Commonly use the useState hook that updates (overwrites) the state.
- UseEffect takes place of the lifecycle methods
Class Component
- Takes advantage of object oriented programming
- Creates objects via constructor function, a built in JavaScript class method
- The 'class', 'constructor', 'super', 'this' and 'new' keyword are needed
- JSX is returned in the render statement
- The render lifecycle must be managed explicitly
- Use the setState and will merge the state
- Method Binding
App.css
* { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: 'Courier New', Courier, monospace; background-color: rgba(125, 137, 238, 0.877); color: whitesmoke; line-height: 1.6; } ul { list-style: none; } h1, h2 { text-align: center; } .container { max-width: 768px; margin: auto; padding: 0 20px; }
App.js
import './App.css'; import Dogs from './Dogs'; import Cats from './Cats'; const App = () => { return ( <div className='container'> <h1>Class to Functional</h1> <Dogs /> <Cats /> </div> ); }; export default App;
Class Component
Cats.js
import React from 'react'; class Cats extends React.Component { render() { return( <> <h1 style={{ color: 'blue' }}>A Class Component</h1> <h1>Hello Cats</h1> </> ) } } export default Cats;
Functional Component w/ES6
Dogs.js
import React from 'react'; const Dogs = () => { return ( <> <h1 style={{ color: 'red' }}>A Functional Component</h1> <h1>Hello Dogs</h1> </> ) }; export default Dogs;
Simple demo rendering a class and functional component
A Class Component with State, Props, and Lifecycle Method
Cats.js
import React from 'react'; import Kittens from './Kittens'; class Cats extends React.Component { constructor() { super(); this.state = { color: 'yellow', name: 'Tartar', kittens:3 }; } componentDidMount() { alert('This componentDidMount to the DOM') } changeColor = () => { this.setState({color: "red"}); } render() { return ( <div> <h1 style={{ color: 'blue' }}>A Class Component</h1> <h2>Hello Cats</h2> <h2> Hello Cats. My name is {this.state.name} and I am the color {this.state.color}. </h2> <Kittens kittens={this.state.kittens}/> <button type='button' onClick={this.changeColor}> Class Change color </button> </div> ); } } export default Cats;
The (Kittens.js) Child Class Component
Kittens.js
import React from 'react' class Kittens extends React.Component{ render() { return <> <h1 style={{ color: 'blue' }}>A Class Component</h1> <h2>Tartar has {this.props.kittens} kittens</h2> </> } } export default Kittens;
Let's Change the Class Component Cats.js to A Functional Component
I am creating new component called 'ChangeCat.js'
Side Note:
The child component called Kittens.js
remained a class but still reads the props from ChangeCat.js
we could go further and change the Kittens.js
to functional component which would be consistent with the paradigm.
App.js
import './App.css'; import Dogs from './Dogs'; import Cats from './Cats'; import ChangeCat from './ChangeCat'; const App = () => { return ( <div className='container'> <h1>Class to Functional</h1> <Dogs /> <Cats /> <ChangeCat /> </div> ); }; export default App;
ChangeCat.js
import React, { useEffect, useState } from 'react'; import Kittens from './Kittens'; const ChangeCat = () => { const [catInfo, setCatInfo] = useState({ name: 'Tartar', color: 'Yellow', kittens: 3 }); useEffect(() => { alert( "This was the componentDidMount in Cats.js but now it's coming from the ChangeCat.js useEffect to the DOM" ); }, []); const handleClick = (e) => setCatInfo({ ...catInfo, color: e.target.value }); return ( <> <h1 style={{ color: 'red' }}>A Functional Component</h1> <h2> Hello Cats. My name is {catInfo.name} and I am the color {catInfo.color} . </h2> <Kittens kittens={catInfo.kittens} /> <button type='button' value='red' onClick={handleClick}> Functional Change Color </button> </> ); }; export default ChangeCat;
Summary
Legacy code is challenging.
- This demo compared
Dogs.js
(functional) andCats.js
(Class) components both can be used in React. - I created a class component with more complexity to include state, passing props to a child class component, and a lifecycle method.
- I changed the
Cats.js
class component to a functional component calledChangeCat.js
- Final Result is a functional component
ChangeCat.js
with a class component child.
Give it a try and convert the rest of the class components to functional components Repo
Links 🔗
❤️❤️❤️
Social
Twitter
Linkedin
Portfolio
Github
🤘
Happy Coding
Top comments (0)