├── package.json
├── public
└── index.html
└── src
├── Callback.js
├── Context.js
├── DebugValue.js
├── Effect.js
├── ImperativeHandle.js
├── LayoutEffect.js
├── Memo.js
├── Reducer.js
├── Ref.js
├── State.js
├── index.js
└── styles.css
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-hooks-examples-v3",
3 | "version": "1.0.0",
4 | "description": "",
5 | "keywords": [],
6 | "main": "src/index.js",
7 | "dependencies": {
8 | "react": "17.0.1",
9 | "react-dom": "17.0.1",
10 | "react-scripts": "4.0.3"
11 | },
12 | "devDependencies": {},
13 | "scripts": {
14 | "start": "react-scripts start",
15 | "build": "react-scripts build",
16 | "test": "react-scripts test --env=jsdom",
17 | "eject": "react-scripts eject"
18 | },
19 | "browserslist": [">0.2%", "not dead", "not ie <= 11", "not op_mini all"]
20 | }
21 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
14 |
23 | React App
24 |
25 |
26 |
27 |
30 |
31 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/src/Callback.js:
--------------------------------------------------------------------------------
1 | import { useState, useEffect, useCallback, memo } from "react";
2 |
3 | const ExpensiveComputationComponent = memo(({ compute, count }) => {
4 | return (
5 |
6 |
computed: {compute(count)}
7 | last re-render {new Date().toLocaleTimeString()}
8 |
9 | );
10 | });
11 |
12 | const CallbackComponent = () => {
13 | const [time, setTime] = useState(new Date());
14 | const [count, setCount] = useState(1);
15 | useEffect(() => {
16 | const timer = setTimeout(() => setTime(new Date()), 1000);
17 | return () => clearTimeout(timer);
18 | });
19 |
20 | const fibonacci = (n) => {
21 | if (n <= 1) {
22 | return 1;
23 | }
24 |
25 | return fibonacci(n - 1) + fibonacci(n - 2);
26 | };
27 |
28 | return (
29 |
30 |
useCallback Example {time.toLocaleTimeString()}
31 |
34 |
38 |
39 | );
40 | };
41 |
42 | export default CallbackComponent;
43 |
--------------------------------------------------------------------------------
/src/Context.js:
--------------------------------------------------------------------------------
1 | import { useState, useContext, createContext } from "react";
2 |
3 | const UserContext = createContext([
4 | {
5 | firstName: "Bob",
6 | lastName: "Bobberson",
7 | suffix: 1,
8 | email: "bobbobberson@example.com"
9 | },
10 | (obj) => obj
11 | ]);
12 |
13 | const LevelFive = () => {
14 | const [user, setUser] = useContext(UserContext);
15 |
16 | return (
17 |
18 |
{`${user.firstName} ${user.lastName} the ${user.suffix} born`}
19 |
26 |
27 | );
28 | };
29 |
30 | const LevelFour = () => (
31 |
32 |
fourth level
33 |
34 |
35 | );
36 |
37 | const LevelThree = () => (
38 |
39 |
third level
40 |
41 |
42 | );
43 |
44 | const LevelTwo = () => (
45 |
46 |
second level
47 |
48 |
49 | );
50 |
51 | const ContextComponent = () => {
52 | const userState = useState({
53 | firstName: "James",
54 | lastName: "Jameson",
55 | suffix: 1,
56 | email: "jamesjameson@example.com"
57 | });
58 |
59 | return (
60 |
61 | first level
62 |
63 |
64 | );
65 | };
66 |
67 | export default ContextComponent;
68 |
--------------------------------------------------------------------------------
/src/DebugValue.js:
--------------------------------------------------------------------------------
1 | import { useState, useEffect, useDebugValue } from "react";
2 |
3 | const useIsRaining = () => {
4 | const [isRaining, setIsRaining] = useState(false);
5 |
6 | useEffect(() => {
7 | // pretend here you'd make an API request to a weather API
8 | // instead we're just going to fake it
9 |
10 | setIsRaining(Math.random() > 0.5);
11 | });
12 |
13 | useDebugValue(isRaining ? "Is Raining" : "Is Not Raining");
14 |
15 | return isRaining;
16 | };
17 |
18 | const DebugValueComponent = () => {
19 | const isRaining = useIsRaining();
20 |
21 | return (
22 |
23 |
useDebugValue Example
24 | Do you need a coat today? {isRaining ? "yes" : "maybe"}
25 |
26 | );
27 | };
28 |
29 | export default DebugValueComponent;
30 |
--------------------------------------------------------------------------------
/src/Effect.js:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from "react";
2 |
3 | const EffectComponent = () => {
4 | const [time, setTime] = useState(new Date());
5 |
6 | useEffect(() => {
7 | const timer = setTimeout(() => setTime(new Date()), 1000);
8 | return () => clearTimeout(timer);
9 | });
10 |
11 | return useEffect Example: {time.toLocaleTimeString()}
;
12 | };
13 |
14 | export default EffectComponent;
15 |
--------------------------------------------------------------------------------
/src/ImperativeHandle.js:
--------------------------------------------------------------------------------
1 | import { useState, useRef, useImperativeHandle, forwardRef } from "react";
2 |
3 | const ElaborateInput = forwardRef(
4 | ({ hasError, placeholder, value, update }, ref) => {
5 | const inputRef = useRef();
6 | useImperativeHandle(ref, () => {
7 | return {
8 | focus() {
9 | inputRef.current.focus();
10 | }
11 | };
12 | });
13 | return (
14 | update(e.target.value)}
18 | placeholder={placeholder}
19 | style={{
20 | padding: "5px 15px",
21 | borderWidth: "3px",
22 | borderStyle: "solid",
23 | borderColor: hasError ? "crimson" : "#999",
24 | borderRadius: "5px",
25 | margin: "0 10px",
26 | textAlign: "center"
27 | }}
28 | />
29 | );
30 | }
31 | );
32 |
33 | const ImperativeHandleComponent = () => {
34 | const [city, setCity] = useState("Seattle");
35 | const [state, setState] = useState("WA");
36 | const [error, setError] = useState("");
37 | const cityEl = useRef();
38 | const stateEl = useRef();
39 |
40 | function validate() {
41 | // lol I found it on StackOverflow : https://stackoverflow.com/a/25677072
42 | if (
43 | !/^([a-zA-Z\u0080-\u024F]+(?:. |-| |'))*[a-zA-Z\u0080-\u024F]+$/.test(
44 | city
45 | )
46 | ) {
47 | setError("city");
48 | cityEl.current.focus();
49 | return;
50 | }
51 |
52 | if (!/^[A-Z]{2}$/.test(state)) {
53 | setError("state");
54 | stateEl.current.focus();
55 | return;
56 | }
57 |
58 | setError("");
59 | alert("valid form!");
60 | }
61 |
62 | return (
63 |
64 |
useImperativeHandle Example
65 |
72 |
79 |
80 |
81 | );
82 | };
83 |
84 | export default ImperativeHandleComponent;
85 |
--------------------------------------------------------------------------------
/src/LayoutEffect.js:
--------------------------------------------------------------------------------
1 | import { useState, useLayoutEffect, useRef } from "react";
2 |
3 | const LayoutEffectComponent = () => {
4 | const [width, setWidth] = useState(0);
5 | const [height, setHeight] = useState(0);
6 | const el = useRef();
7 |
8 | useLayoutEffect(() => {
9 | setWidth(el.current.clientWidth);
10 | setHeight(el.current.clientHeight);
11 | });
12 |
13 | return (
14 |
15 |
useLayoutEffect Example
16 | textarea width: {width}px
17 | textarea height: {height}px
18 |
25 | );
26 | };
27 |
28 | export default LayoutEffectComponent;
29 |
--------------------------------------------------------------------------------
/src/Memo.js:
--------------------------------------------------------------------------------
1 | import { useState, useMemo } from "react";
2 |
3 | const fibonacci = (n) => {
4 | if (n <= 1) {
5 | return 1;
6 | }
7 |
8 | return fibonacci(n - 1) + fibonacci(n - 2);
9 | };
10 |
11 | const MemoComponent = () => {
12 | const [num, setNum] = useState(1);
13 | const [isGreen, setIsGreen] = useState(true);
14 | const fib = useMemo(() => fibonacci(num), [num]);
15 |
16 | return (
17 |
18 |
setIsGreen(!isGreen)}
20 | style={{ color: isGreen ? "limegreen" : "crimson" }}
21 | >
22 | useMemo Example
23 |
24 |
25 | Fibonacci of {num} is {fib}
26 |
27 |
28 |
29 | );
30 | };
31 |
32 | export default MemoComponent;
33 |
--------------------------------------------------------------------------------
/src/Reducer.js:
--------------------------------------------------------------------------------
1 | import { useReducer } from "react";
2 |
3 | // fancy logic to make sure the number is between 0 and 255
4 | const limitRGB = (num) => (num < 0 ? 0 : num > 255 ? 255 : num);
5 |
6 | const step = 50;
7 |
8 | const reducer = (state, action) => {
9 | switch (action.type) {
10 | case "INCREMENT_R":
11 | return Object.assign({}, state, { r: limitRGB(state.r + step) });
12 | case "DECREMENT_R":
13 | return Object.assign({}, state, { r: limitRGB(state.r - step) });
14 | case "INCREMENT_G":
15 | return Object.assign({}, state, { g: limitRGB(state.g + step) });
16 | case "DECREMENT_G":
17 | return Object.assign({}, state, { g: limitRGB(state.g - step) });
18 | case "INCREMENT_B":
19 | return Object.assign({}, state, { b: limitRGB(state.b + step) });
20 | case "DECREMENT_B":
21 | return Object.assign({}, state, { b: limitRGB(state.b - step) });
22 | default:
23 | return state;
24 | }
25 | };
26 |
27 | const ReducerComponent = () => {
28 | const [{ r, g, b }, dispatch] = useReducer(reducer, { r: 0, g: 0, b: 0 });
29 |
30 | return (
31 |
32 |
useReducer Example
33 |
34 | r
35 |
36 |
37 |
38 |
39 | g
40 |
41 |
42 |
43 |
44 | b
45 |
46 |
47 |
48 |
49 | );
50 | };
51 |
52 | export default ReducerComponent;
53 |
--------------------------------------------------------------------------------
/src/Ref.js:
--------------------------------------------------------------------------------
1 | import { useState, useRef } from "react";
2 |
3 | const RefComponent = () => {
4 | const [stateNumber, setStateNumber] = useState(0);
5 | const numRef = useRef(0);
6 |
7 | function incrementAndDelayLogging() {
8 | setStateNumber(stateNumber + 1);
9 | numRef.current++;
10 | setTimeout(
11 | () => alert(`state: ${stateNumber} | ref: ${numRef.current}`),
12 | 1000
13 | );
14 | }
15 |
16 | return (
17 |
18 |
useRef Example
19 |
20 | state: {stateNumber}
21 | ref: {numRef.current}
22 |
23 | );
24 | };
25 |
26 | export default RefComponent;
27 |
--------------------------------------------------------------------------------
/src/State.js:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 |
3 | const StateComponent = () => {
4 | const [isGreen, setIsGreen] = useState(true);
5 |
6 | return (
7 | setIsGreen(!isGreen)}
9 | style={{ color: isGreen ? "limegreen" : "crimson" }}
10 | >
11 | useState Example
12 |
13 | );
14 | };
15 |
16 | export default StateComponent;
17 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import ReactDOM from "react-dom";
2 | import State from "./State";
3 | import Effect from "./Effect";
4 | import Context from "./Context";
5 | import Ref from "./Ref";
6 | import Reducer from "./Reducer";
7 | import Memo from "./Memo";
8 | import Callback from "./Callback";
9 | import LayoutEffect from "./LayoutEffect";
10 | import ImperativeHandle from "./ImperativeHandle";
11 | import DebugValue from "./DebugValue";
12 |
13 | import "./styles.css";
14 |
15 | function App() {
16 | return (
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | );
39 | }
40 |
41 | const rootElement = document.getElementById("root");
42 | ReactDOM.render(, rootElement);
43 |
--------------------------------------------------------------------------------
/src/styles.css:
--------------------------------------------------------------------------------
1 | .App {
2 | font-family: sans-serif;
3 | text-align: center;
4 | }
5 |
--------------------------------------------------------------------------------