https://github.com/ch0ripain/react-class-based-components
🧙♂️ React class-based components 🧙♂️
https://github.com/ch0ripain/react-class-based-components
react react-class-components reactjs
Last synced: 10 months ago
JSON representation
🧙♂️ React class-based components 🧙♂️
- Host: GitHub
- URL: https://github.com/ch0ripain/react-class-based-components
- Owner: ch0ripain
- Created: 2024-12-04T22:47:37.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2024-12-10T02:49:46.000Z (about 1 year ago)
- Last Synced: 2025-02-14T15:47:07.642Z (12 months ago)
- Topics: react, react-class-components, reactjs
- Language: JavaScript
- Homepage:
- Size: 223 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
🧙♂️ React class-based components 🧙♂️
Class-based components were used a lot a while ago, more specifically in versions prior to React 16.8. In that version React added hooks and with that a more functional way of working based on functional components.
In this project I will demonstrate how to translate functional components to class components and also where one can continue using class based components and how to use some class oriented hooks like useState(), useEffect(), useContext().
## ⚡️Functional component to class-based component
```javascript
//Functional
const User = (props) => {
return
};
//Class
import { Component } from 'react';
class User extends Component {
constructor(){
super()
}
render (){
return
}
}
//Using a class component is the same thing
```
- Component must be imported from React
- User must extends Component ➡️ it allow to use all the methods from the parent (Component)
- constructor() ➡️ enables you to provide any custom initialization that must be done before any other methods can be called on an instantiated object.
- super() ➡️ call the constructor of its parent class to access the parent's properties and methods
- render() ➡️ inherited method that allows to render the value inside
- this ➡️ to refer our class props context (props are automatically forwarded by react)
In the example given above the constructor() and super() are not really needed because i don't want to provide any custom initialization or change any inherited property like state from the parent.
---
### ⚡️useState()
```javascript
//Functional
import { useState } from 'react';
const Users = () => {
const [showUsers, setShowUsers] = useState(true);
const toggleUsersHandler = () => {
setShowUsers((curState) => !curState);
};
return (
{showUsers ? 'Hide' : 'Show'} Users
{showUsers && usersList}
)
//Class
class Users extends Component {
constructor() {
super();
this.state = { showUsers: true }
}
toggleUsersHandler() {
this.setState((prevState) => {
return { showUsers: !prevState.showUsers }
})
}
render() {
...
return (
{this.state.showUsers ? 'Hide' : 'Show'} Users
{this.state.showUsers && usersList}
)
}
```
The changes I need to make to manage state in my class shown above are:
- this.state ➡️ property inherited from the Component whose value must always be an Object ➡️ {}
- toggleUsersHandler() ➡️ as my class method and also using the keyword this to refer my class context
- this.state.showUsers ➡️ always refer to the state on my class
- bind() ➡️ to pass data as an argument to the function of a class based component for context purposes
> [!NOTE]
> You can avoid use "bind" syntax if you use arrow function syntax instead ➡️ toggleUsersHandler() = () => { ... };
If you want to know more about bind take a look on these links
[ReactJS-Bind-Method-GG](https://www.geeksforgeeks.org/reactjs-bind-method/)
[ReactJS-Bind-Method-StackOverflow](https://stackoverflow.com/questions/60774235/what-does-bindthis-is-exactly-doing-in-this-example-of-the-react-app#:~:text=%22bind%22%20method%20is%20used%20to,the%20value%20of%20parent%20component.)
---
### ⚡️useEffect()
```javascript
//Class
class UserFinder extends Component {
constructor() {
super()
this.state = { filteredUsers: DUMMY_USERS, searchTerm: '' }
}
searchChangeHandler(event) {
this.setState({ searchTerm: event.target.value })
}
//Loading users when component is rendered
componentDidMount() {
this.setState({ filteredUsers: DUMMY_USERS })
}
//Updating users with state/props changes
componentDidUpdate(prevProps, prevState) {
if (prevState.searchTerm !== this.state.searchTerm) {
this.setState({ filteredUsers: DUMMY_USERS.filter((user) => user.name.includes(this.state.searchTerm)) })
}
}
render() {...}
}
```
When using useEffect() on class-based component there are 3 main methods that allow me to handle that hook:
- componentDidMount() ➡️ equivalent to useEffect() without deps, only executed once the component is rendered.
- componentDidUpdate() ➡️ equivalent to useEffect() with deps, it is executed every time a property or state changes. We also need to manage those changes and what will happen next.
- componentWillUnmount() ➡️ equivalent to useEffect() cleanup function, executed when the component is unmounted
This is a example of componentWillUnmount()
```javascript
class User extends Component {
...
componentWillUnmount() {
console.log('User component unmounted')
}
...
}
```
---
### ⚡️Using Context in Class-based components
```javascript
//First i create my context on my standalone context file
import React from 'react';
const UsersContext = React.createContext({
users: []
});
export default UsersContext;
```
```javascript
//Then i wrap a parent component in common with all the update state logic
import UsersContext from './store/users-context';
function App() {
const usersContext = {
users: DUMMY_USERS
}
return (
);
}
```
```javascript
//Last, use the context in the child component i want
import UsersContext from '../store/users-context';
class UserFinder extends Component {
...
//defining context
static contextType = UsersContext; //always must be static contextType prop
...
//state
constructor() {
super()
this.state = { filteredUsers: [], searchTerm: '' }
}
...
//using the context
componentDidMount() {
this.setState({ filteredUsers: this.context.users })
}
```
---
### ⚡️Error Boundaries
This is probably the main reason to use a class-based component nowadays, as React doesn't support error handling yet (it could barely be implemented using try catch or something like that)
```javascript
//Create your error boundary as a class component and handle all error logic within it.
class ErrorBoundary extends Component {
constructor() {
super();
this.state = { hasError: false }
}
componentDidCatch(error) {
console.log(error)
this.setState({ hasError: true })
}
render() {
if (this.state.hasError) {
return
Something went wrong D:
}
return this.props.children //If no error catched just return the children component value
}
}
```
-
componentDidCatch() ➡️ catches exceptions generated in child components.
```javascript
// Wrap child components where errors should occur
import ErrorBoundary from './ErrorBoundary';
//Dummy error on Users.js
componentDidUpdate() {
if (this.props.users.length === 0) {
throw new Error('No users provided')
}
}
```
So if an error occurs in a child component that is wrapped with my error-component boundary class with all the error logic, this would be rendered:
```javascript
render() {
if (this.state.hasError) {
return
Something went wrong D:
//This message will be seen by the user}
return this.props.children
}
```
---
🐸 This project is a practice exercise I learned from the Academind's React Course 🐸