Skip to content

Commit 71c01a9

Browse files
Surjit Kumar SahooSurjit Kumar Sahoo
authored andcommitted
add what are hooks
1 parent f7b7e0c commit 71c01a9

12 files changed

Lines changed: 334 additions & 23 deletions

File tree

docs/1.architecture/6.state-management/3.global-state-redux.mdx

Whitespace-only changes.

docs/2.misc-structural-guides/_category_.json renamed to docs/1.architecture/7.misc-structural-guides/_category_.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"label": "Misc Structural Guidelines",
33
"collapsed": true,
4-
"position": 4,
4+
"position": 7,
55
"link": {
66
"type": "generated-index",
77
"description": "Guidelines for choosing naming-conventions, avoiding nested if-checks and other structural best practices in React applications. These guidelines help maintain code readability, consistency, and ease of maintenance across your React projects."

docs/2.misc-structural-guides/naming-convention.md renamed to docs/1.architecture/7.misc-structural-guides/naming-convention.md

File renamed without changes.

docs/1.architecture/_category_.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"label": "Architecture",
33
"position": 2,
4+
"collapsed": false,
45
"link": {
56
"type": "generated-index",
67
"description": "Robust code architecture is essential for building scalable and maintainable applications. This section covers the principles and practices that guide the design of a well-structured codebase."

docs/4.performance/1.class-components-vs-function-components.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,74 @@ sidebar_position: 1
33
---
44

55
# Class Components Vs Function Components
6+
7+
## Class Components
8+
9+
Back in the days of React components were classes, and the components were following an imperative approach. And with the introduction of hooks, react has moved towards a declarative approach. While it has become easier to create the same component with hooks in significantly less code compared to class components, it has also become way easier to write buggy, slow and unreadable hard-to-understand bad code. **So it has become more important than ever to understand how react works.**
10+
11+
In the class components, the UI code is in the render method of the class, and the states, functions, event handlers everything was outside the render method. They were properties or methods of the component class. To re-render a component, it just needs to call the render method, and no function or state variables will be re-created or re-instantiated.
12+
13+
```jsx
14+
// Simple React class component example
15+
import React, { Component } from 'react';
16+
17+
class Counter extends Component {
18+
// State is defined as a property of the class
19+
state = {
20+
count: 0,
21+
};
22+
23+
// Event handler is a method of the class
24+
increment = () => {
25+
this.setState({ count: this.state.count + 1 });
26+
};
27+
28+
// UI code is inside the render method
29+
// Calling this method wont re-create increment method or the state properties of the class
30+
render() {
31+
return (
32+
<div>
33+
<p>Count: {this.state.count}</p>
34+
<button onClick={this.increment}>Increment</button>
35+
</div>
36+
);
37+
}
38+
}
39+
40+
export default Counter;
41+
```
42+
43+
## Function Components
44+
45+
But now that render method has become the entire component. All the states, state-modifier functions, event handlers, life-cycle hooks/functions, everything lives inside that component function. Anytime that component needs to be updated or re-rendered, the component function is executed.
46+
47+
But function component is just a javascript function. When a javascript function gets called again, all of its arguments and internal variables/properties, everything get re-created and re-defined. So in the react components all the props, all the functions defined inside the component, all the variables including states, state-modifier function, prop restructured value, everything gets re-created and re-defined.
48+
49+
```jsx
50+
import React, { useState } from 'react';
51+
52+
// The entire function body runs on every render,
53+
// so all variables and functions defined here are re-created each time
54+
function Counter() {
55+
// State and state-modifier function are created on every render
56+
const [count, setCount] = useState(0);
57+
58+
// This function is re-created on every render
59+
const increment = () => {
60+
setCount(count + 1);
61+
};
62+
63+
return (
64+
<div>
65+
<p>Count: {count}</p>
66+
<button onClick={increment}>Increment</button>
67+
</div>
68+
);
69+
}
70+
71+
export default Counter;
72+
```
73+
74+
:::tip render --> re-create states and functions --> re-render --> repeat 🧨💣
75+
But then... wouldn't that trigger infinite re-renders if everything is always being re-created (changed)? Yes, it would. That's where hooks come into the picture.
76+
:::
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
---
2+
sidebar_position: 2
3+
slug: what-are-hooks
4+
---
5+
6+
# What Are Hooks?
7+
8+
:::info Hooks are all about memoization
9+
It is an optimization technique.
10+
The memoization function caches the last return value and would return the cached value if the inputs are the same as the previous function call.
11+
:::
12+
13+
Hooks memoize and protect the variables and functions within the React component from being re-created on each re-render. Different hooks memoize different things.
14+
15+
That's the default behavior in class components, but we are trying to mimic that in function components!
16+
17+
## `useCallback`
18+
19+
This hook memoizes a function. It takes a callback function as param to memoize. Whenever the component re-renders, the useCallback function will be called again and again, and each time it'll return the exact same function reference, as long as the dependency doesn't change. So the returned function will remain same, as if it was defined outside the react-component.
20+
21+
```tsx
22+
function UserComponent({ user }) {
23+
const userName = useCallback(
24+
// 👇 This function is memoized
25+
// highlight-start
26+
() => {
27+
const name = user.name;
28+
return `user: ${name}`;
29+
},
30+
// highlight-end
31+
[user],
32+
);
33+
}
34+
```
35+
36+
In this example, `UserComponent` component, which a javascript function can be called as many times as required as part of re-rendering the component, but if the `user` prop doesn't change, then `userName` function will remain exactly same. It will not be re-created.
37+
38+
But when the `user` prop does change, then the `useCallback` hook will return a brand new function, re-created new instance.
39+
40+
## `useMemo`
41+
42+
This hook has the exact same signature as `useCallback`. Except, it memoizes a value, not the function. The value returned from the callback function is memoized, not the function itself. If it's dependencies don't change, it will not call the callback function it'll return the previous value which the hook has cached.
43+
44+
It will call the callback function for a fresh value only when the dependencies change
45+
46+
```tsx
47+
function UserComponent({ user }) {
48+
const userName = useMemo(() => {
49+
const name = user.name;
50+
// 👇 This return value is memoized
51+
// highlight-next-line
52+
return `user: ${name}`;
53+
}, [user]);
54+
}
55+
```
56+
57+
In this example, useMemo will call the passed callback function on the first render and return the return-value of the callback function. Then whenever the component re-renders the useMemo function will be called to get the value for `userName`, but the useMemo will not call the callback function if the dependency: user object hasn't changed, instead it will return the previous cached value.
58+
59+
## `useState`
60+
61+
It's a weird one. All other hooks memoize something that's passed to the hook function as param. But unlike other hooks, It's not memoizing the value passed to the useState function. It's memoizing the return value of the useState function. And the passed value is just the initial value to be memoized.
62+
63+
The memoized value doesn't change when some dependency (input) change, it doesn't even have a dependency array. Instead it gives us a dedicated function for changing the memoized value. And this function not only updates the memoized value but also triggers the re-render of the component.
64+
65+
```jsx
66+
function UserComponent({ user: usr }) {
67+
const [
68+
// 👇 This value is memoized
69+
// highlight-next-line
70+
user,
71+
setUser,
72+
] = useState(usr);
73+
}
74+
```
75+
76+
## `useEffect`
77+
78+
This hook memoizes the side-effect. Yeah it sounds weird, basically, we're telling react, to run this callback anytime the dependency values change.
79+
80+
```jsx
81+
function UserComponent({ user }) {
82+
useEffect(
83+
// 👇 This function (side-effect) is memoized
84+
// highlight-next-line
85+
() => doSomething(),
86+
[user],
87+
);
88+
}
89+
```
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
sidebar_position: 3
3+
slug: use-effect-is-dangerous
4+
---
5+
6+
# `useEffect` is Dangerous!
7+
8+
:::danger
9+
Always avoid using `useEffect` if you have any alternate solution.
10+
:::
11+
12+
:::info Remember
13+
It runs only after the commit phase, i.e after the re-render changes have been committed to the DOM.
14+
:::
15+
16+
## Common pitfalls
17+
18+
### Don't use it to update the local state if the props change.
19+
20+
```jsx title="DON'T 💩💣"
21+
function Message({ msg }) {
22+
const [msgState, setMsgState] = useState(msg);
23+
24+
useEffect(() => setMsgState(msg), [msg]);
25+
26+
return <div>{msgState}</div>;
27+
}
28+
```
29+
30+
- When the `msg` prop changes from parent, it'll call the `<Message/>` component function again passing the new updated `msg` (re-render triggered).
31+
- Then Message component will re-render by re-calculating the changes in the UI elements, and commit the changes to the browser. Only after that, your `useEffect` will run, setting the new msg in the state. That will again trigger re-render. But you already got the updated msg in previous render, you do not need another re-render!!
32+
33+
```jsx title="DO ✅"
34+
function Message({ msg }) {
35+
return <div>{msg}</div>;
36+
}
37+
```

docusaurus.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ const config: Config = {
4545

4646
plugins: ['@docusaurus/theme-live-codeblock'],
4747

48+
staticDirectories: ['static', 'public'],
4849
presets: [
4950
[
5051
'classic',

src/pages/index.module.css

Lines changed: 110 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@
44
*/
55

66
.heroBanner {
7-
padding: 4rem 0;
7+
padding-top: 4rem;
8+
margin-bottom: -4rem;
9+
padding-bottom: 0;
810
text-align: center;
911
position: relative;
1012
overflow: hidden;
13+
background-color: transparent;
14+
z-index: 3;
1115
}
1216

1317
@media screen and (max-width: 996px) {
@@ -16,8 +20,112 @@
1620
}
1721
}
1822

19-
.buttons {
23+
.main {
24+
position: relative;
25+
min-height: 32rem;
26+
}
27+
28+
.mainImage {
29+
width: 100%;
30+
height: auto;
31+
display: block;
32+
position: relative;
33+
z-index: 1;
34+
box-shadow: 0 -4rem 4rem -8px rgba(0, 0, 0, 0.85);
35+
}
36+
37+
.bottomOverlay {
38+
position: absolute;
39+
left: 0;
40+
right: 0;
41+
bottom: 0;
42+
z-index: 2;
43+
display: flex;
44+
flex-direction: column;
45+
align-items: center;
46+
padding-bottom: 4rem;
47+
width: 100%;
48+
pointer-events: none;
49+
}
50+
51+
.description {
52+
max-width: 50rem;
53+
margin: 0 auto 1.5rem auto;
54+
position: static;
55+
left: unset;
56+
right: unset;
57+
bottom: unset;
58+
background: rgba(255, 255, 255, 0.1);
59+
backdrop-filter: blur(18px) saturate(180%);
60+
-webkit-backdrop-filter: blur(18px) saturate(180%);
61+
border: 1px solid rgba(255, 255, 255, 0.14);
62+
border-radius: 1rem;
63+
padding: 1.25rem 2rem;
64+
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
65+
z-index: 3;
66+
pointer-events: auto;
67+
}
68+
69+
.button {
2070
display: flex;
2171
align-items: center;
2272
justify-content: center;
73+
z-index: 3;
74+
pointer-events: auto;
75+
position: relative;
76+
overflow: hidden;
77+
padding: 1rem 3rem;
78+
border-radius: 0.5rem;
79+
cursor: pointer;
80+
}
81+
82+
.buttonLink {
83+
all: unset;
84+
color: white;
85+
font-weight: 600;
86+
font-size: 1.2rem;
87+
}
88+
89+
.button::before {
90+
content: '';
91+
position: absolute;
92+
inset: -2px;
93+
z-index: -1;
94+
border-radius: 0.5rem;
95+
padding: 2px;
96+
background: linear-gradient(270deg, #ff6ec4, #7873f5, #1fd1f9, #ff6ec4);
97+
background-size: 600% 600%;
98+
animation: animated-border 4s linear infinite;
99+
}
100+
101+
@keyframes animated-border {
102+
0% {
103+
background-position: 0% 50%;
104+
}
105+
50% {
106+
background-position: 100% 50%;
107+
}
108+
100% {
109+
background-position: 0% 50%;
110+
}
111+
}
112+
113+
.button > * {
114+
position: relative;
115+
z-index: 1;
116+
background: inherit;
117+
border-radius: 0.5rem;
118+
}
119+
120+
@media screen and (max-width: 996px) {
121+
.main {
122+
min-height: 20rem;
123+
}
124+
.bottomOverlay {
125+
padding-bottom: 1rem;
126+
}
127+
.description {
128+
padding: 1rem 1rem;
129+
font-size: 0.98rem;
130+
}
23131
}

0 commit comments

Comments
 (0)