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)