Skip to content

Commit 01494c4

Browse files
committed
update
1 parent d1396dd commit 01494c4

21 files changed

+9524
-11569
lines changed
297 KB
Loading
42 KB
Loading
306 KB
Loading
171 KB
Loading
69 KB
Loading
95.8 KB
Loading
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
---
2+
slug: intro-to-react-fiber
3+
title: Introduction to React Fiber
4+
description: A comprehensive guide to understanding React Fiber, its architecture, and how it improves React performance
5+
keywords: [react, react fiber, javascript, web development, performance]
6+
image: ./diff.jpg
7+
authors: [gazcn007]
8+
tags: [react, javascript, web development]
9+
---
10+
11+
import { ReactFiber, SlideShow } from '@patternize/components';
12+
13+
:::info
14+
This blog will explain React Fiber Internal Algorithms, we will:
15+
16+
- Revisit how React diff works
17+
- Problems with Tree Traversal
18+
- Morris Traversal
19+
20+
It's recommended to have a basic understanding of React, virtualDOM, and diff before reading this blog.
21+
:::
22+
23+
You can first experience the difference between React Fiber (v17+) and pre-Fiber (v16) by playing with the playground below:
24+
25+
<ReactFiber />
26+
27+
You can tell a huge difference between the two versions, the old reconcilor is very slow, but the fiber one is very smooth.
28+
29+
![](./diff.jpg)
30+
31+
### Diff Calculation of React
32+
33+
React's diff calculation is based on the virtualDOM, which is a tree structure that represents the UI. When a state change happens, React will calculate the difference between the old virtualDOM and the new virtualDOM, and then apply the changes to the realDOM.
34+
35+
![MinimalEDTrees](./MinimalEDTrees.jpg)
36+
37+
However, calculating the edit distance of two unordered trees is NP-Complete, and the standard algorithm needs at least a runtime of **O(n^3)**.
38+
39+
:::tip
40+
41+
There are papers that show that the problem is NP-Complete. Because it is equivalent to a graph isomorphism problem.
42+
43+
![Np-Hard.jpg](./NpHard.jpg)
44+
45+
:::
46+
47+
React uses a **heuristic approach** that compares nodes level-by-level rather than doing an exhaustive node-by-node comparison. While this may sometimes update more nodes than strictly necessary, it ensures no required updates are missed while being much more efficient than a full tree traversal. The algorithm trades perfect accuracy for speed and predictability.
48+
49+
![](./ReactDoc.jpg)
50+
51+
You can see the heuristic approach of diff traversal in the gif below - **React compares the tree level by level instead of node by node.**
52+
53+
![](./DiffTraversal.gif)
54+
55+
### Problem with Recursion
56+
57+
What’s wrong with doing a full tree traversal for diff in the above animation?
58+
59+
Well, there are two problems with traversing the tree using recursion, we all know in computer science:
60+
61+
1. For any tree recursion, the call stack is O(n)
62+
2. It is impossible to pause the traversal and stop the stack from growing while you are doing recursion.
63+
64+
**Here is an interactive slide show of the call stack of the recursion stack:**
65+
66+
(You can navigate back and forth using Previous and Next button)
67+
68+
export const StackSlideShow = () => {
69+
const images = [
70+
'/slideshow/React-Stack/React-Fiber.001.jpeg',
71+
'/slideshow/React-Stack/React-Fiber.002.jpeg',
72+
'/slideshow/React-Stack/React-Fiber.003.jpeg',
73+
'/slideshow/React-Stack/React-Fiber.004.jpeg',
74+
'/slideshow/React-Stack/React-Fiber.005.jpeg',
75+
'/slideshow/React-Stack/React-Fiber.006.jpeg',
76+
'/slideshow/React-Stack/React-Fiber.007.jpeg'
77+
];
78+
return <SlideShow maxWidth='1000px' maxHeight='460px' images={images}/>;
79+
}
80+
81+
<StackSlideShow />
82+
83+
## Solution to the problems - Morris Traversal
84+
85+
Morris Traversal is a way to traverse a tree without using recursion. It is a linear time algorithm that uses a single stack to store the nodes.
86+
87+
**Here is an interactive slide show of traversing the tree with Morris Traversal:**
88+
89+
export const FiberSlideShow = () => {
90+
const images = [
91+
'/slideshow/React-Fiber/React-Fiber.001.jpeg',
92+
'/slideshow/React-Fiber/React-Fiber.002.jpeg',
93+
'/slideshow/React-Fiber/React-Fiber.003.jpeg',
94+
'/slideshow/React-Fiber/React-Fiber.004.jpeg',
95+
'/slideshow/React-Fiber/React-Fiber.005.jpeg',
96+
'/slideshow/React-Fiber/React-Fiber.006.jpeg',
97+
'/slideshow/React-Fiber/React-Fiber.007.jpeg',
98+
'/slideshow/React-Fiber/React-Fiber.008.jpeg',
99+
'/slideshow/React-Fiber/React-Fiber.009.jpeg',
100+
'/slideshow/React-Fiber/React-Fiber.010.jpeg',
101+
'/slideshow/React-Fiber/React-Fiber.011.jpeg'
102+
];
103+
return <SlideShow maxWidth='1000px' maxHeight='460px' images={images}/>;
104+
}
105+
106+
<FiberSlideShow />
107+
108+
**With Morris Traversal, the call stack is constant O(1) space. Runtime is O(1) for each evaluation. And you can pause the traversal anytime!**
109+
110+
This is exactly what React Fiber is doing in their code - adding more path between the nodes to turn a tree into a graph like Morris Traversal.
111+
112+
![](graph.jpg)
113+
114+
## React Fiber with concurrency
115+
116+
What you can do with fiber once you have O(1) time and space for each evaluation and being able to pause the traversal is concurrent rendering.
117+
118+
This is how React Fiber achieves concurrent rendering, you can see the animation below:
119+
120+
export const ConcurrencySlideShow = () => {
121+
const images = [
122+
'/slideshow/React-Fiber-Concurrency/React-Fiber-Concurrency.001.jpeg',
123+
'/slideshow/React-Fiber-Concurrency/React-Fiber-Concurrency.002.jpeg',
124+
'/slideshow/React-Fiber-Concurrency/React-Fiber-Concurrency.003.jpeg',
125+
'/slideshow/React-Fiber-Concurrency/React-Fiber-Concurrency.004.jpeg',
126+
'/slideshow/React-Fiber-Concurrency/React-Fiber-Concurrency.005.jpeg',
127+
'/slideshow/React-Fiber-Concurrency/React-Fiber-Concurrency.006.jpeg',
128+
'/slideshow/React-Fiber-Concurrency/React-Fiber-Concurrency.007.jpeg'
129+
];
130+
return <SlideShow maxWidth='1000px' maxHeight='460px' images={images}/>;
131+
}
132+
133+
<ConcurrencySlideShow />

‎docs/Patterns/BitManipulation/Introduction.md‎

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,20 @@ sidebar_label: Introduction
55
---
66

77
## Power of 2
8-
1 << x === 2^x
98

9+
```javascript
10+
(1 << x === 2) ^ x;
11+
```
1012

1113
## Log Base of 2
12-
# log(a) base b = log(a)/log(b)
13-
32 >> 5 === log(32)/log(2)
1414

15+
```javascript
16+
# log(a) base b = log(a)/log(b)
17+
32 >> 5 === log(32)/log(2)
18+
```
1519

1620
## Count Ones In Binary Representation
21+
1722
- `n&(n-1)` rule: is used when you want to quickly count how many `1s` in your binary number, every-time you do `n&(n-1)`, a `1` in your binary form will be removed:
1823

1924
```java
@@ -45,8 +50,6 @@ int count_one(int n) {
4550
}
4651
```
4752

48-
49-
5053
## References:
51-
- https://leetcode.com/problems/sum-of-two-integers/discuss/84278/A-summary%3A-how-to-use-bit-manipulation-to-solve-problems-easily-and-efficiently
5254

55+
- https://leetcode.com/problems/sum-of-two-integers/discuss/84278/A-summary%3A-how-to-use-bit-manipulation-to-solve-problems-easily-and-efficiently

‎docs/QuestionBank/Leetcode/101. Symmetric Tree.md‎

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
---
22
id: LC101
3-
title: LC101. Symmetric Tree
4-
sidebar_label: LC101. Symmetric Tree
5-
tags: ['Patterns/Tree', 'DataStructures/Tree']
3+
title: Symmetric Tree
4+
sidebar_label: Symmetric Tree
5+
tags: ["Patterns/Tree", "DataStructures/Tree"]
66
---
77

88
## Problem Description
@@ -22,6 +22,7 @@ For example, this binary tree [1, 2, 2, 3, 4, 4, 3] is symmetric:
2222
```
2323

2424
But the following [1, 2, 2, null, 3, null, 3] is not:
25+
2526
```
2627
1
2728
/ \
@@ -30,26 +31,29 @@ But the following [1, 2, 2, null, 3, null, 3] is not:
3031
3 3
3132
```
3233

33-
## Solution
34+
## Solution
3435

3536
### High level strategy
37+
3638
To check whether two nodes are identical, we can check the following conditions:
39+
3740
1. If both nodes are null, then they **are the same**.
3841
2. If one of the nodes is null, then they **are not the same**.
3942
3. If the value of one node is not equal to the value of the other, then they **are not the same**.
4043

4144
To check whether a tree is symmetrical, we can simply apply the logics above to the opposite nodes on each side of the tree. That is, we compare the right child of the left child with the left child of the right child, so on and so forth. We recurse down both sides of the root node, and return true if and only if both sides return true. The time complexity of this solution is **O(n)**, where 'n' is equal to the number of nodes. The space complexity of this solution is **O(logn)**, or **O(h)**, where 'h' is equal to the height of the tree.
4245

43-
### Code
46+
### Code
47+
4448
import Tabs from '@theme/Tabs';
4549
import TabItem from '@theme/TabItem';
4650

4751
<Tabs
48-
defaultValue="js"
49-
values={[
50-
{ label: 'Javascript', value: 'js', },
51-
{ label: 'Java', value: 'java', }
52-
]
52+
defaultValue="js"
53+
values={[
54+
{ label: 'Javascript', value: 'js', },
55+
{ label: 'Java', value: 'java', }
56+
]
5357
}>
5458
<TabItem value="js">
5559

@@ -64,18 +68,19 @@ import TabItem from '@theme/TabItem';
6468
**/
6569

6670
const isSymmetric = (root) => {
67-
if (root === null) return true;
68-
return isSame(root.left, root.right);
71+
if (root === null) return true;
72+
return isSame(root.left, root.right);
6973
};
7074

7175
const isSame = (node1, node2) => {
72-
if (node1 === null && node2 === null) return true;
73-
if (node1 === null || node2 === null) return false;
74-
if (node1.val !== node2.val) return false;
75-
76-
return isSame(node1.left, node2.right) && isSame(node1.right, node2.left);
76+
if (node1 === null && node2 === null) return true;
77+
if (node1 === null || node2 === null) return false;
78+
if (node1.val !== node2.val) return false;
79+
80+
return isSame(node1.left, node2.right) && isSame(node1.right, node2.left);
7781
};
7882
```
83+
7984
</TabItem>
8085
<TabItem value="java">
8186

@@ -92,25 +97,26 @@ private boolean isSymmetricHelp(TreeNode left, TreeNode right){
9297
return isSymmetricHelp(left.left, right.right) && isSymmetricHelp(left.right, right.left);
9398
}
9499
```
100+
95101
</TabItem>
96102
</Tabs>
97103

98104
## Other Solutions
105+
99106
<details>
100107
<summary>BFS Approach</summary>
101108

102-
103109
```java
104110
/**
105111
* We can also explore each level through BFS,
106112
* then iterate through all nodes in each level to see if they are a mirror
107-
* (same idea as checking if a string is a palindrome).
113+
* (same idea as checking if a string is a palindrome).
108114
*/
109115

110116
class Solution {
111117
public boolean isSymmetric(TreeNode root) {
112118
if (root == null) return true;
113-
Queue<TreeNode> queue = new LinkedList<>();
119+
Queue<TreeNode> queue = new LinkedList<>();
114120
queue.add(root);
115121
while(queue.size() > 0) {
116122
int size = queue.size();
@@ -136,4 +142,5 @@ class Solution {
136142
}
137143
}
138144
```
145+
139146
</details>

0 commit comments

Comments
 (0)