Skip to content

Commit

Permalink
feat(add): react hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
seognil committed Nov 17, 2019
1 parent 05e620a commit 09ccf05
Show file tree
Hide file tree
Showing 28 changed files with 733 additions and 0 deletions.
10 changes: 10 additions & 0 deletions react/hooks-api-usage/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Hooks API - Learning By Doing

## 教材

- [Hooks API 索引](https://zh-hans.reactjs.org/docs/hooks-reference.html)
- [React Hooks 学习指南](https://fe.rualc.com/note/react-hooks.html)

## Local Dev

`parcel ./useContext/index.html`
14 changes: 14 additions & 0 deletions react/hooks-api-usage/useCallback/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<div id="app"></div>

<script src="script.tsx"></script>
</body>
</html>
45 changes: 45 additions & 0 deletions react/hooks-api-usage/useCallback/script.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import * as React from 'react';
import { useCallback } from 'react';
import ReactDOM from 'react-dom';

// * ------------------------------------------------

let ticker = 0;
let updateFlag = 0;

const sameRandomFunctionFactory = () => {
const Rand = Math.random();
return () => Rand;
};

// * ------------------------------------------------

const App = ({ updateFlag }) => {
const now = Date.now();

const cb = useCallback(sameRandomFunctionFactory(), [updateFlag]);
const result = cb();

return (
<div>
<p>
timer:
<br />
{now}
</p>
<p>
result of useCallback: ('updateFlag' props changes by 2 secs)
<br />
{result}
</p>
</div>
);
};

// * ------------------------------------------------

setInterval(() => {
ticker += 1 / 2;
updateFlag = Math.round(ticker);
ReactDOM.render(<App updateFlag={updateFlag} />, document.querySelector('#app'));
}, 1000);
14 changes: 14 additions & 0 deletions react/hooks-api-usage/useContext/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<div id="app"></div>

<script src="script.tsx"></script>
</body>
</html>
42 changes: 42 additions & 0 deletions react/hooks-api-usage/useContext/script.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import * as React from 'react';
import { createContext, useState, useContext } from 'react';
import ReactDOM from 'react-dom';

const genColor = () => `hsla(${Math.random() * 360}, 70%, 50%)`;

// * ------------------------------------------------

type MyContext = { color: string; changer: (any) => void };

const ThemeContext = createContext<MyContext>(null);

// * --------------------------------

const Comp = () => {
const { color, changer } = useContext(ThemeContext);

return (
<button style={{ color, fontSize: '2em' }} onClick={changer}>
Hello World! Click to change color
</button>
);
};

// * --------------------------------

const App = () => {
const [state, setState] = useState({ color: 'green' });

const { color } = state;
const changer = () => setState({ color: genColor() });

return (
<ThemeContext.Provider value={{ color, changer }}>
<Comp />
</ThemeContext.Provider>
);
};

// * ------------------------------------------------

ReactDOM.render(<App />, document.querySelector('#app'));
14 changes: 14 additions & 0 deletions react/hooks-api-usage/useEffect/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<div id="app"></div>

<script src="script.tsx"></script>
</body>
</html>
26 changes: 26 additions & 0 deletions react/hooks-api-usage/useEffect/script.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as React from 'react';
import { useEffect, useState } from 'react';
import ReactDOM from 'react-dom';

const App = () => {
const [count, setCount] = useState(0);

useEffect(() => {
const timer = setTimeout(() => {
console.log(`You clicked ${count} times`);
}, 1000);
return () => {
clearTimeout(timer);
console.log(`cancel timer`);
};
});

return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
};

ReactDOM.render(<App />, document.querySelector('#app'));
14 changes: 14 additions & 0 deletions react/hooks-api-usage/useImperativeHandle/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<div id="app"></div>

<script src="script.tsx"></script>
</body>
</html>
33 changes: 33 additions & 0 deletions react/hooks-api-usage/useImperativeHandle/script.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as React from 'react';
import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
import ReactDOM from 'react-dom';

// * ------------------------------------------------

const ChildInput = forwardRef((props, ref) => {
const realRef = useRef<HTMLInputElement>(null);

useImperativeHandle(ref, () => realRef.current);

return <input type="text" name="child input" ref={realRef} />;
});

// * --------------------------------

const App = () => {
const inputRef = useRef(null);

useEffect(() => {
inputRef.current.focus();
}, []);

return (
<div>
<ChildInput ref={inputRef} />
</div>
);
};

// * ------------------------------------------------

ReactDOM.render(<App />, document.querySelector('#app'));
14 changes: 14 additions & 0 deletions react/hooks-api-usage/useLayoutEffect/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<div id="app"></div>

<script src="script.tsx"></script>
</body>
</html>
23 changes: 23 additions & 0 deletions react/hooks-api-usage/useLayoutEffect/script.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as React from 'react';
import { useLayoutEffect, useRef, useState } from 'react';
import ReactDOM from 'react-dom';

const App = () => {
const [height, setHeight] = useState(0);
const refer = useRef<HTMLHeadingElement>(null);

useLayoutEffect(() => {
const $dom = refer.current;
const domHeight = $dom.getBoundingClientRect().height;
if (height !== domHeight) setHeight(domHeight);
});

return (
<div>
<h1 ref={refer}>hello</h1>
<h2>{height}</h2>
</div>
);
};

ReactDOM.render(<App />, document.querySelector('#app'));
14 changes: 14 additions & 0 deletions react/hooks-api-usage/useMemo/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<div id="app"></div>

<script src="script.tsx"></script>
</body>
</html>
56 changes: 56 additions & 0 deletions react/hooks-api-usage/useMemo/script.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import * as React from 'react';
import { useMemo } from 'react';
import ReactDOM from 'react-dom';

import { memoizeWith } from 'ramda';
import { memoize } from 'lodash-es';

// * ------------------------------------------------

let ticker = 0;
let updateFlag = 0;

const getRandom = () => Math.random();

// * try different tools, but react useMemo only keep the previous deps to compare
const randamMemo = memoizeWith(() => updateFlag, getRandom);
const lodashMemo = memoize(getRandom, () => updateFlag);

// * ------------------------------------------------

const App = ({ updateFlag }) => {
const now = Date.now();

let result;

{
result = useMemo(getRandom, [updateFlag]);

// * try different tools, try declare here, they would fail
// result = randamMemo();
// result = lodashMemo();
}

return (
<div>
<p>
timer:
<br />
{now}
</p>
<p>
result of useMemo: ('updateFlag' props changes by 2 secs)
<br />
{result}
</p>
</div>
);
};

// * ------------------------------------------------

setInterval(() => {
ticker += 1 / 2;
updateFlag = Math.round(ticker);
ReactDOM.render(<App updateFlag={updateFlag} />, document.querySelector('#app'));
}, 1000);
14 changes: 14 additions & 0 deletions react/hooks-api-usage/useReducer/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<div id="app"></div>

<script src="script.tsx"></script>
</body>
</html>
27 changes: 27 additions & 0 deletions react/hooks-api-usage/useReducer/script.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import * as React from 'react';
import { useReducer } from 'react';
import ReactDOM from 'react-dom';

type MyReducer = React.Reducer<{ value: number }, { type: string; payload?: number }>;

const reducer: MyReducer = (state, action) => {
const { value } = state;
const { type, payload = 1 } = action;
const nextValue = type === 'plus' ? value + payload : type === 'minus' ? value - payload : value;
return { value: nextValue };
};

const App = () => {
const [state, dispatch] = useReducer(reducer, { value: 0 });

return (
<>
Count by useReducer: {state.value}
<br />
<button onClick={() => dispatch({ type: 'plus', payload: 5 })}>plus 5</button>
<button onClick={() => dispatch({ type: 'minus', payload: 3 })}>minus 3</button>
</>
);
};

ReactDOM.render(<App />, document.querySelector('#app'));
14 changes: 14 additions & 0 deletions react/hooks-api-usage/useRef/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<div id="app"></div>

<script src="script.tsx"></script>
</body>
</html>
Loading

0 comments on commit 09ccf05

Please sign in to comment.