├── .gitignore
├── 10-modularity
├── src
│ ├── main.js
│ ├── App.js
│ ├── utils
│ │ └── debounceFrame.js
│ ├── components
│ │ └── CounterAndMeow.js
│ └── core
│ │ └── MyReact.js
└── index.html
├── 02-only-one-state
└── index.html
├── 01-make-state-frame
└── index.html
├── README.md
├── 03-multi-state-bug
└── index.html
├── 05-no-state-change
└── index.html
├── 06-dont-render-no-change
└── index.html
├── 04-multi-state-success
└── index.html
├── 07-unnecessary-render
└── index.html
├── 08-refactor-rendering-by-debounce
└── index.html
└── 09-abstract-render
└── index.html
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .vscode
3 | .DS_Store
4 | *.iml
5 | node_modules
6 |
--------------------------------------------------------------------------------
/10-modularity/src/main.js:
--------------------------------------------------------------------------------
1 | import { render } from "./core/MyReact.js";
2 | import { App } from "./App.js";
3 |
4 | render(App, document.querySelector('#app'));
5 |
--------------------------------------------------------------------------------
/10-modularity/src/App.js:
--------------------------------------------------------------------------------
1 | import { CounterAndMeow } from "./components/CounterAndMeow.js";
2 |
3 | export const App = () => `
4 |
5 | ${CounterAndMeow()}
6 |
7 | `;
--------------------------------------------------------------------------------
/10-modularity/src/utils/debounceFrame.js:
--------------------------------------------------------------------------------
1 | export function debounceFrame (callback) {
2 | let nextFrameCallback = -1;
3 | return () => {
4 | cancelAnimationFrame(nextFrameCallback);
5 | nextFrameCallback = requestAnimationFrame(callback)
6 | }
7 | };
8 |
--------------------------------------------------------------------------------
/10-modularity/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | MyReact App
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/10-modularity/src/components/CounterAndMeow.js:
--------------------------------------------------------------------------------
1 | import { useState } from "../core/MyReact.js";
2 |
3 | export function CounterAndMeow () {
4 | const [count, setCount] = useState(1);
5 | const [cat, setCat] = useState('야옹! ');
6 |
7 | function countMeow (newCount) {
8 | setCount(newCount);
9 | setCat('야옹! '.repeat(newCount));
10 | }
11 |
12 | window.increment = () => countMeow(count + 1);
13 | window.decrement = () => countMeow(count - 1);
14 |
15 | return `
16 |
17 |
고양이가 ${count}번 울어서 ${cat}
18 |
19 |
20 |
21 | `;
22 | }
23 |
--------------------------------------------------------------------------------
/02-only-one-state/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
10 |
40 |
41 |
--------------------------------------------------------------------------------
/01-make-state-frame/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
10 |
44 |
45 |
--------------------------------------------------------------------------------
/10-modularity/src/core/MyReact.js:
--------------------------------------------------------------------------------
1 | import { debounceFrame } from "../utils/debounceFrame.js";
2 |
3 | function MyReact () {
4 | const options = {
5 | currentStateKey: 0,
6 | renderCount: 0,
7 | states: [],
8 | root: null,
9 | rootComponent: null,
10 | }
11 |
12 | function useState (initState) {
13 | const { currentStateKey: key, states } = options;
14 | if (states.length === key) states.push(initState);
15 |
16 | const state = states[key];
17 | const setState = (newState) => {
18 | states[key] = newState;
19 | _render();
20 | }
21 | options.currentStateKey += 1;
22 | return [ state, setState ];
23 | }
24 |
25 | const _render = debounceFrame(() => {
26 | const { root, rootComponent } = options;
27 | if (!root || !rootComponent) return;
28 | root.innerHTML = rootComponent();
29 | options.currentStateKey = 0;
30 | options.renderCount += 1;
31 | });
32 |
33 |
34 | function render (rootComponent, root) {
35 | options.root = root;
36 | options.rootComponent = rootComponent;
37 | _render();
38 | }
39 |
40 | return { useState, render };
41 |
42 | }
43 |
44 | export const { useState, render } = MyReact();
45 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Vanilla Javascript로 React UseState Hook 만들기
2 | 이 저장소는 `Vanilla Javascript로 React UseState Hook 만들기` 아티클에서 사용되는 코드를 모아놓는 용도로 사용되었습니다.
3 |
4 | - [01. state 틀 구성](https://junilhwang.github.io/simple-use-state/01-make-state-frame/index.html)
5 | - [02. 한 개의 state만 있을 경우](https://junilhwang.github.io/simple-use-state/02-only-one-state/index.html)
6 | - [03. 여러 개의 state가 있을 경우 버그 발생](https://junilhwang.github.io/simple-use-state/03-multi-state-bug/index.html)
7 | - [04. 여러 개의 state가 있을 경우 정상 작동](https://junilhwang.github.io/simple-use-state/04-multi-state-success/index.html)
8 | - [05. state 값이 동일할 경우](https://junilhwang.github.io/simple-use-state/05-no-state-change/index.html)
9 | - [06. state 값이 동일할 경우 렌더링 방지](https://junilhwang.github.io/simple-use-state/06-dont-render-no-change/index.html)
10 | - [07. 불필요한 render 발생](https://junilhwang.github.io/simple-use-state/07-unnecessary-render/index.html)
11 | - [08. debounce로 렌더링을 리팩토링](https://junilhwang.github.io/simple-use-state/08-refactor-rendering-by-debounce/index.html)
12 | - [09. render 추상화](https://junilhwang.github.io/simple-use-state/09-abstract-render/index.html)
13 | - [10. 모듈화](https://junilhwang.github.io/simple-use-state/10-modularity/index.html)
14 |
--------------------------------------------------------------------------------
/03-multi-state-bug/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
10 |
58 |
59 |
--------------------------------------------------------------------------------
/05-no-state-change/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
10 |
59 |
60 |
--------------------------------------------------------------------------------
/06-dont-render-no-change/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
10 |
66 |
67 |
--------------------------------------------------------------------------------
/04-multi-state-success/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
10 |
70 |
71 |
--------------------------------------------------------------------------------
/07-unnecessary-render/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
10 |
67 |
68 |
--------------------------------------------------------------------------------
/08-refactor-rendering-by-debounce/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
10 |
75 |
76 |
--------------------------------------------------------------------------------
/09-abstract-render/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
10 |
92 |
93 |
--------------------------------------------------------------------------------