Skip to content

Commit c7a58db

Browse files
committed
useEffect replacing life cycle methods
1 parent de1a6a1 commit c7a58db

8 files changed

+125
-11
lines changed
File renamed without changes.

React/hooks-useEffect.md renamed to React/Hooks/useEffect-basics-1.md

+27-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
**useEffect**
2-
31
### you can think of useEffect Hook as componentDidMount, componentDidUpdate, and componentWillUnmount combined.
42

53
Mutations, subscriptions, timers, logging, and other side effects are not allowed inside the main body of a function component (referred to as React’s render phase). Doing so will lead to confusing bugs and inconsistencies in the UI. **According to doc function passed to useEffect fires after layout and paint.**
@@ -10,7 +8,7 @@ In React class components, the render method itself shouldn’t cause side effec
108

119
This is why in React classes, we put side effects into componentDidMount and componentDidUpdate.
1210

13-
## Effects Without Cleanup {#effects-without-cleanup}
11+
### Effects Without Cleanup {#effects-without-cleanup}
1412

1513
Sometimes, we want to **run some additional code after React has updated the DOM.** Network requests, manual DOM mutations, and logging are common examples of effects that don't require a cleanup. We say that because we can run them and immediately forget about them. Let's compare how classes and Hooks let us express such side effects.
1614

@@ -19,7 +17,7 @@ Sometimes, we want to **run some additional code after React has updated the DOM
1917
In React class components, the `render` method itself shouldn't cause side effects. It would be too early -- we typically want to perform our effects _after_ React has updated the DOM.
2018
This is why in React classes, we put side effects into `componentDidMount` and `componentDidUpdate`. Coming back to our example, here is a React counter class component that updates the document title right after React makes changes to the DOM:
2119

22-
```js{9-15}
20+
```js
2321
class Example extends React.Component {
2422
constructor(props) {
2523
super(props);
@@ -48,19 +46,23 @@ class Example extends React.Component {
4846

4947
Note how **we have to duplicate the code between these two lifecycle methods in class.**
5048
This is because in many cases we want to perform the same side effect regardless of whether the component just mounted, or if it has been updated. Conceptually, we want it to happen after every render -- but React class components don't have a method like this. We could extract a separate method but we would still have to call it in two places.
51-
Now let's see how we can do the same with the `useEffect` Hook.
49+
50+
Now let's see how we can do the same with the `**useEffect**` Hook.
5251

5352
### Example Using Hooks {#example-using-hooks}
5453

5554
We've already seen this example at the top of this page, but let's take a closer look at it:
5655

57-
```js{1,6-8}
56+
```js
5857
import React, { useState, useEffect } from "react";
58+
5959
function Example() {
6060
const [count, setCount] = useState(0);
61+
6162
useEffect(() => {
6263
document.title = `You clicked ${count} times`;
6364
});
65+
6466
return (
6567
<div>
6668
<p>You clicked {count} times</p>
@@ -76,4 +78,22 @@ The state and state update function come from the state hook called useState
7678

7779
**Why is `useEffect` called inside a component?** Placing `useEffect` inside the component lets us access the `count` state variable (or any props) right from the effect. We don't need a special API to read it -- it's already in the function scope. Hooks embrace JavaScript closures and avoid introducing React-specific APIs where JavaScript already provides a solution.
7880

79-
**Does `useEffect` run after every render?** Yes! By default, it runs both after the first render _and_ after every update. (We will later talk about [how to customize this](#tip-optimizing-performance-by-skipping-effects).) Instead of thinking in terms of "mounting" and "updating", you might find it easier to think that effects happen "after render". React guarantees the DOM has been updated by the time it runs the effects.
81+
**Does `useEffect` run after every render?** Yes! By default, it runs both after the first render _and_ after every update. (We separately talk about below [how to customize this](#tip-optimizing-performance-by-skipping-effects). Instead of thinking in terms of "mounting" and "updating", you might find it easier to think that effects happen "after render". React guarantees the DOM has been updated by the time it runs the effects.
82+
83+
#### Great explanation of the second array argument to useEffect() - so to control when useEffect() will run
84+
85+
[https://medium.com/javascript-in-plain-english/state-management-with-react-hooks-no-redux-or-context-api-8b3035ceecf8](https://medium.com/javascript-in-plain-english/state-management-with-react-hooks-no-redux-or-context-api-8b3035ceecf8)
86+
87+
**By default, effects run after every completed render. But, you can choose to fire it only when certain values have changed, passing an array of variables as a second optional parameter.**
88+
89+
```js
90+
// Without the second parameter
91+
useEffect(() => {
92+
console.log("I will run after every render");
93+
});
94+
95+
// With the second parameter
96+
useEffect(() => {
97+
console.log("I will run only when valueA changes");
98+
}, [valueA]);
99+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
For each of the three most common lifecycle methods (componentDidMount, componentDidUpdate, componentWillUnmount), I will demonstrate a class style implementation
2+
3+
### componentDidMount
4+
5+
```js
6+
// First the class component Example
7+
class Example extends React.Component {
8+
componentDidMount() {
9+
console.log("I am mounted!");
10+
}
11+
render() {
12+
return null;
13+
}
14+
}
15+
16+
// With hooks the same above Example component
17+
function Example() {
18+
useEffect(() => console.log("I am mounted"), []);
19+
return null;
20+
}
21+
```
22+
23+
#### The second argument is an array of values (usually props).
24+
25+
If any of the value in the array changes, the callback will be fired after every render.
26+
When it's not present, the callback will always be fired after every render.
27+
When it's an empty list, the callback will only be fired once, similar to componentDidMount.
28+
29+
### componentDidUpdate
30+
31+
```js
32+
componentDidMount() {
33+
console.log('mounted or updated');
34+
}
35+
36+
componentDidUpdate() {
37+
console.log('mounted or updated');
38+
}
39+
useEffect(() => console.log('mounted or updated'));
40+
```
41+
42+
There is not a straight forward implementation in hooks to replace componentDidUpdate. **The useEffect function can be used to trigger callbacks after every render of the component including after component mounts and component updates.**
43+
However this is not a big problem since most of the time we place similar functions in componentDidMount and componentDidUpdate.
44+
45+
#### Further Reading
46+
47+
- 1. [https://dev.to/trentyang/replace-lifecycle-with-hooks-in-react-3d4n](https://dev.to/trentyang/replace-lifecycle-with-hooks-in-react-3d4n)
48+
- 2. [https://alligator.io/react/replacing-component-lifecycles-with-useeffect/](https://alligator.io/react/replacing-component-lifecycles-with-useeffect/)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#### Replacing componentWillUnmount with useEffect()
2+
3+
```js
4+
componentWillUnmount() {
5+
console.log('will unmount');
6+
}
7+
8+
// Now to replicate the above, just return a function inside useEffect() which will do the same job that I amd doing inside componentWillUnmount
9+
useEffect(() => {
10+
return () => {
11+
console.log('will unmount');
12+
}
13+
}, []);
14+
```
15+
16+
When you return a function in the callback passed to useEffect, the returned function will be called before the component is removed from the UI.
17+
18+
As we discussed previously, we need to pass an empty list as the second argument for useEffect so that the callback will only be called once. This apply to the returned function too.
19+
20+
Normally we do cleanups in the componentWillUnmount. Let's say you want to create an event listener on componentDidMount and clean it up on componentDidUnmount. With hooks the code will be combined into one callback function.

React/hooks-useReducers.md renamed to React/Hooks/useReducers-basics-1.md

+2-4
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,11 @@ Given the return value from **useReducer** is in the form object, I can do de-st
66

77
`const [state, dispatch] = useReducer(reducer, initialState)`
88

9-
By the [Official doc on the above array-destructuring synatax](https://reactjs.org/docs/hooks-state.html#tip-what-do-square-brackets-mean)
9+
By the [Official doc on the above array-destructuring syntax](https://reactjs.org/docs/hooks-state.html#tip-what-do-square-brackets-mean)
1010

1111
It means that we’re making two new variables **state** and **dispatch**, where **state** is set to the first value returned by **useReducer**, and **dispatch** is the second. It is equivalent to this code:
1212

13-
Every useReducer comes with its own dispatch function.
14-
15-
The **useReducer** function is tightly coupled to its reducer and its dispatch function. We dispatch action objects to that reducer only.
13+
Every useReducer comes with its own dispatch function. The **useReducer** function is tightly coupled to its reducer and its dispatch function. We dispatch action objects to that reducer only that useReducer() function takes as its first argument.
1614

1715
#### Now an example to convert a useState() to a useReducer()
1816

React/hooks-useState.md renamed to React/Hooks/useState.md

+26
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,32 @@ The setState it returns is almost the same used by class components—it can acc
9696

9797
Each call to useState is paired with a component, with its state persisting across renders. This means that you can call useState multiple times within a single function component to get multiple independent state values. Because the setState returned isn't scoped to a single component, we can define stateful behaviors independent of the component. This enables powerful new ways to abstract stateful logic.
9898

99+
#### When we want to display the current count in a class, we read this.state.count:
100+
101+
```js
102+
<p>You clicked {this.state.count} times</p>
103+
```
104+
105+
**In a function, we can use count directly:**
106+
107+
`<p>You clicked {count} times</p>`
108+
109+
#### Updating State
110+
111+
In a class, we need to call this.setState() to update the count state:
112+
113+
```js
114+
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
115+
Click me
116+
</button>
117+
```
118+
119+
**In a function, we already have setCount and count as variables so we don’t need this:**
120+
121+
```js
122+
<button onClick={() => setCount(count + 1)}>Click me</button>
123+
```
124+
99125
#### Further Reading
100126

101127
- [https://medium.com/@vcarl/everything-you-need-to-know-about-react-hooks-8f680dfd4349](https://medium.com/@vcarl/everything-you-need-to-know-about-react-hooks-8f680dfd4349)
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
While useReducer with its reducer is a part of how Redux works, it isn’t Redux. The useReducer function is tightly coupled to its reducer which holds also true for its dispatch function. We dispatch action objects to that reducer only. Whereas in Redux, the dispatch function sends the action object to the store which distributes it to all its combined reducer functions. You can think of Redux as one global event bus which takes any events (actions) and processes them into a new state based on the action’s payload and the previous state.
2+
3+
In other words, Redux provides a global store where you can keep app data centralized. useReducer is localized to a specific component.

0 commit comments

Comments
 (0)