React 常用 Hooks 实战

对于新手 react 玩家来说,了解常用的 React Api 是一件重要的事情,这篇文章可以帮组你很快的了解常用 Api,帮助你在开发中快速而有效的完成任务。

React 中常用的五个 Hooks

useState

用于在函数组件中添加状态,状态的更新会触发组件重新渲染。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import React, { useState } from "react";

function Counter() {
const [count, setCount] = useState(0);

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

export default Counter;

useEffect

用于在函数组件中执行副作用操作,如数据获取、订阅、手动更改 DOM 等。它相当于 componentDidMountcomponentDidUpdatecomponentWillUnmount 的结合。

副作用一定要是改变的数据,像对象这种引用型的数据,虽然你主观认为数据改变了,但是并没有改变引用,所以特定监听不到。但是可以配合useState 实现监听。

示例:

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

function Example() {
const [count, setCount] = useState(0);

useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);

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

export default Example;

useContext

用于共享状态而无需手动通过每一级组件传递 props。

示例:

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

const MyContext = React.createContext();

function MyComponent() {
const value = useContext(MyContext);
return <div>{value}</div>;
}

function App() {
return (
<MyContext.Provider value="Hello, World!">
<MyComponent />
</MyContext.Provider>
);
}

export default App;

useReducer

用于更复杂的状态管理逻辑,类似于 useState,但适用于包含多个子值或复杂状态逻辑的情况。

示例:

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 React, { useReducer } from "react";

const initialState = { count: 0 };

function reducer(state, action) {
switch (action.type) {
case "increment":
return { count: state.count + 1 };
case "decrement":
return { count: state.count - 1 };
default:
throw new Error();
}
}

function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);

return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: "increment" })}>+</button>
<button onClick={() => dispatch({ type: "decrement" })}>-</button>
</div>
);
}

export default Counter;

useRef

用于访问 DOM 元素或保存一个可变值,该值在组件重新渲染时不会改变。

示例:

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

function TextInputWithFocusButton() {
const inputEl = useRef(null);

const onButtonClick = () => {
inputEl.current.focus();
};

return (
<div>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</div>
);
}

export default TextInputWithFocusButton;

使用 useReducer 进行复杂状态管理

为什么使用 useReduceruseReducer 在处理包含多个子值或复杂状态逻辑时更合适。通过定义一个 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
29
jsx复制代码;
import React, { useReducer } from "react";

const initialState = { count: 0 };

function reducer(state, action) {
switch (action.type) {
case "increment":
return { count: state.count + 1 };
case "decrement":
return { count: state.count - 1 };
default:
throw new Error();
}
}

function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);

return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: "increment" })}>+</button>
<button onClick={() => dispatch({ type: "decrement" })}>-</button>
</div>
);
}

export default Counter;

使用 memo 进行组件优化

** 为什么使用 memo:**React.memo 是一个高阶组件,可以将组件包装在其中以避免不必要的重新渲染。React.memo 通过浅比较 props 来决定是否重新渲染组件。

示例:

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

const ChildComponent = memo(({ name }) => {
console.log("ChildComponent rendered");
return <div>Hello, {name}</div>;
});

function ParentComponent() {
const [name, setName] = React.useState("John");

return (
<div>
<ChildComponent name={name} />
<button onClick={() => setName(name === "John" ? "Doe" : "John")}>
Change Name
</button>
</div>
);
}

export default ParentComponent;

在上述示例中,ChildComponent 只有在 name 改变时才会重新渲染。通过 React.memo 包装组件,可以有效地减少不必要的渲染,提高性能。

使用 useMemouseCallback 进行性能优化

useMemo

** 为什么使用 useMemo:**useMemo 用于缓存计算结果,从而避免在每次渲染时都进行耗时计算。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import React, { useMemo } from "react";

function Example({ items }) {
const expensiveCalculation = (items) => {
// 假设这里有一个耗时的计算
return items.reduce((total, item) => total + item, 0);
};

const total = useMemo(() => expensiveCalculation(items), [items]);

return <div>Total: {total}</div>;
}

export default Example;

useCallback

** 为什么使用 useCallback:**useCallback 用于缓存函数实例,从而避免在每次渲染时都创建新的函数实例,特别是在将函数传递给子组件时非常有用。

示例:

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

function Example() {
const [count, setCount] = useState(0);

const increment = useCallback(() => {
setCount((prevCount) => prevCount + 1);
}, []);

return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
}

export default Example;

总结

这些示例展示了 React 中常用的 Hooks 及其使用场景。通过合理运用这些 Hooks,可以有效地管理组件状态、处理副作用、优化性能,提升开发效率和应用性能。