Essential React Hooks

Reducer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import { useState } from "react";

export default function App() {
const [count, setCount] = useState(0);

const handleIncrement = () => {
setCount(count + 1);
}

const handleDecrement = () => {
setCount(count - 1);
}

return (
<div style={{ padding: 10 }}>
<button onClick={handleIncrement}>+</button>
<span> {count} </span>
<button onClick={handleDecrement}>-</button>
</div>
);
}

使用Reducer改造后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import { useReducer } from "react";

function countReducer(state, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}


export default function App() {
const [state, dispatch] = useReducer(countReducer, 0);

const handleIncrement = () => dispatch({ type: 'INCREMENT' });
const handleDecrement = () => dispatch({ type: 'DECREMENT' });

return (
<div style={{ padding: 10 }}>
<button onClick={handleIncrement}>+</button>
<span> {state} </span>
<button onClick={handleDecrement}>-</button>
</div>
);
}

useRef

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React, { useRef } from 'react';

export default function UseRefExample() {
// Create a ref
const inputRef = useRef(null);

// Function to focus the input
const focusInput = () => {
inputRef.current.focus();
};

return (
<div>
<h2>useRef Example</h2>
<input ref={inputRef} placeholder="Type something" />
<button onClick={focusInput}>Focus the input</button>
</div>
);
}

Components

普通的Child组件,父组件不能直接访问到。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import React, { useRef } from 'react';


function Child() {
return (
<div>
子组件
</div>
)
}

export default function UseRefExample() {
const childRef = useRef()

function handleClick() {

}
return (
<div>
<Child ref={childRef} />
<button onClick={handleClick}>按钮</button>
</div>

)
}

修正后的代码
使用useImperativeHandle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import React, { forwardRef, useImperativeHandle, useRef } from 'react';


const Child = forwardRef(function (props, ref) {

useImperativeHandle(ref, () => {
return {
// 父组件调用子组件的方法
handleClick() {
console.log('子组件的方法')
}
}
})

return (
<div>
子组件
</div>
)

})

export default function UseRefExample() {
const childRef = useRef()

function handleClick() {
childRef.current.handleClick()
}
return (
<div>
<Child ref={childRef} />
<button onClick={handleClick}>按钮</button>
</div>

)
}

useEffect

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import React, { useState, useEffect } from 'react';

export default function UseEffectExample() {
const [count, setCount] = useState(0);

// Similar to componentDidMount and componentDidUpdate
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;

// Optional cleanup function (similar to componentWillUnmount)
return () => {
document.title = 'React App';
};
}, [count]); // Only re-run if count changes

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

useMemo

示例代码如下:

如果子组件需要进行一些复杂的运算,
在父组件发生变化的时候,子组件的输入没有变,但是也会触发重新渲染。
实际上,输入没有变,重复渲染计算是不必要的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import { useState } from "react";


function DoSomeMath({ value }) {
console.log("DoSomeMath组件重新渲染了");
let result = 0;
for (let i = 0; i < 1000000; i++) {
result += value * 2;
}

return (
<div>
<p>输入内容: {value}</p>
<p>经过复杂计算的数据: {result}</p>
</div>
)
}

export default function App() {

const [inputValue, setInputValue] = useState(5);
const [count, setCount] = useState(0);

return (
<div>
<p>count的值为: {count}</p>
<button onClick={() => setCount(count + 1)}>点击更新</button>
<br />
<br />
<input
type="number"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<DoSomeMath value={inputValue} />
</div>
)
}

useMemo(func, dep)

修改后的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import { useState, useMemo } from "react";

function DoSomeMath({ value }) {
const result = useMemo(() => {
console.log("DoSomeMath组件重新渲染了");
let result = 0;
for (let i = 0; i < 1000000; i++) {
result += value * 2;
}
return result;
}, [value]);
return (
<div>
<p>输入内容: {value}</p>
<p>经过复杂计算的数据: {result}</p>
</div>
)
}

export default function App() {

const [inputValue, setInputValue] = useState(5);
const [count, setCount] = useState(0);

return (
<div>
<p>count的值为: {count}</p>
<button onClick={() => setCount(count + 1)}>点击更新</button>
<br />
<br />
<input
type="number"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<DoSomeMath value={inputValue} />
</div>
)
}

useCallBack

与useMemo类似,useMemo记忆化的是数据,
useCallback记忆化的是函数(函数式组件也是函数)。

父组件发生变化时,不想子组件重新渲染。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import { useState } from "react";

function Button({ onClick }) {
console.log('Button渲染了');
return <button onClick={onClick}>子组件</button>
}

export default function App() {
const [count, setCount] = useState(0);

const handleUpdate = () => {
setCount(count + 1);
}

const handleClick = () => {
console.log('点击按钮');
}

return (
<div>
<p>Count: {count}</p>
<button onClick={handleUpdate}>更新</button>
<br />
<Button onClick={handleClick}></Button>
</div>
)
}

修改代码

  1. 将Button组件 使用memo
  2. 将参数handleClick改成setCallback
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import { useState, memo, useCallback } from "react";

const Button = memo(function ({ onClick }) {
console.log('Button渲染了');
return <button onClick={onClick}>子组件</button>
})
export default function App() {
const [count, setCount] = useState(0);

const handleUpdate = () => {
setCount(count + 1);
}

const handleClick = useCallback(() => {
console.log('点击按钮');
}, [])

return (
<div>
<p>Count: {count}</p>
<button onClick={handleUpdate}>更新</button>
<br />
<Button onClick={handleClick}></Button>
</div>
)
}


Essential React Hooks
https://www.hardyhu.cn/2024/12/23/Essential-React-Hooks/
Author
John Doe
Posted on
December 23, 2024
Licensed under