Hooks
useState
useState 是 React Hooks 中最常用的 hook 之一,它允许您在函数组件中使用状态。它接受一个初始状态值,并返回一个数组,其中包含当前状态和一个更新状态的函数。每次更新状态时,组件都会重新渲染。
const [count, setCount] = useState(0);
参数说明:
initialState:初始状态值。
返回值:
state:当前状态值。setState:用于更新状态值的函数。
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
};
return (
<div>
<p>You clicked {count} times</p>
<button onClick={handleClick}>Click me</button>
</div>
);
}
export default Counter;
详解:
- 在函数组件中使用
useState hook 可以创建一个状态变量和一个更新状态变量的函数。 useState 接收一个初始状态值,并返回一个数组,其中第一个元素是当前状态值,第二个元素是更新状态值的函数。- 调用更新状态值的函数将触发组件的重新渲染。
useState hook 可以被多次使用,以创建多个状态变量和对应的更新函数。
使用函数更新状态值:
setState(prevState => {
return /* 新状态值 */;
});
参数说明:
prevState:前一个状态值。
示例:
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(prevCount => prevCount + 1);
};
return (
<div>
<p>You clicked {count} times</p>
<button onClick={handleClick}>Click me</button>
</div>
);
}
export default Counter;
详解:
- 当您需要使用前一个状态值计算新的状态值时,可以使用函数更新状态值的方式。
- 函数更新状态值将接收前一个状态值作为参数,并返回新的状态值。
- 函数更新状态值将始终在同步更新之前执行,并且可以避免由于异步更新而引起的竞态条件。
使用惰性初始化:
const [state, setState] = useState(() => {
return /* 初始状态值 */;
});
参数说明:
() => {}:返回初始状态值的函数。
示例:
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(() => {
const initialCount = Number(window.localStorage.getItem('count') || 0);
return initialCount;
});
const handleClick = () => {
setCount(prevCount => prevCount + 1);
};
useEffect(() => {
window.localStorage.setItem('count', count);
}, [count]);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={handleClick}>Click me</button>
</div>
);
}
export default Counter;
详解:
useState hook 的参数也可以是一个返回初始状态值的函数,用于惰性初始化状态。- 惰性初始化可以延迟计算初始状态值,直到组件首次渲染时执行。
- 这对于从网络或本地存储中获取数据作为初始状态值非常有用。
使用多个状态变量:
const [state1, setState1] = useState(initialState1);
const [state2, setState2] = useState(initialState2);
示例:
import React, { useState } from 'react';
function UserForm() {
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [email, setEmail] = useState('');
const handleSubmit = event => {
event.preventDefault();
console.log(`Name: ${firstName} ${lastName}, Email: ${email}`);
};
return (
<form onSubmit={handleSubmit}>
<label>
First name:
<input type="text" value={firstName} onChange={e => setFirstName(e.target.value)} />
</label>
<label>
Last name:
<input type="text" value={lastName} onChange={e => setLastName(e.target.value)} />
</label>
<label>
Email:
<input type="text" value={email} onChange={e => setEmail(e.target.value)} />
</label>
<button type="submit">Submit</button>
</form>
);
}
export default UserForm;
详解:
useState hook 可以被多次使用,以创建多个状态变量和对应的更新函数。- 对于每个状态变量,必须使用对应的更新函数来更新状态。
- 使用多个状态变量可以让您在函数组件中保存多个相关数据,而无需使用类组件。
总结:useState 是 React Hooks 中最常用的 hook 之一,它允许您在函数组件中使用状态。使用 useState,您可以创建状态变量和对应的更新函数,并在函数组件中保存数据。您还可以使用函数更新状态值、惰性初始化状态、使用多个状态变量等。
useEffect
useEffect 是另一个常用的 hook,它允许您在组件渲染后执行副作用操作。它接受一个回调函数和一个依赖项数组,这些依赖项会影响该回调函数的执行。如果依赖项未发生变化,则该回调函数不会再次执行。
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);
useEffect 是 React Hooks 中常用的 hook 之一,它允许您在组件挂载、卸载或更新时执行副作用操作。以下是 useEffect 的全面详解:
useEffect(() => {
// effect
return () => {
// cleanup
};
}, [dependency]);
参数说明:
effect:副作用操作的函数。cleanup:清理副作用操作的函数。dependency:依赖数组,用于控制effect 函数何时重新运行。
返回值:
- 无。
示例:
import React, { useState, useEffect } from 'react';
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);
const handleClick = () => {
setCount(count + 1);
};
return (
<div>
<p>You clicked {count} times</p>
<button onClick={handleClick}>Click me</button>
</div>
);
}
export default Counter;
详解:
useEffect hook 允许您在组件挂载、卸载或更新时执行副作用操作。 useEffect 钩useEffect 接收一个函数作为副作用操作,并在组件挂载、卸载或更新时调用该函数。useEffect 函数可以返回一个清理函数,在组件卸载或更新时调用该函数。useEffect 函数还可以接收一个依赖数组,以控制何时重新运行effect 函数。- 如果依赖数组为空,
effect 函数将仅在组件挂载和卸载时运行。 - 如果依赖数组不为空,
effect 函数将在组件挂载和每次依赖项发生更改时运行。
使用 useEffect hook 可以处理以下副作用操作:
- 发起网络请求或访问浏览器 API。
- 添加或删除 DOM 元素。
- 订阅或取消订阅事件。
- 记录日志或统计数据。
使用多个 useEffect hook:
useEffect(() => {
// effect1
return () => {
// cleanup1
};
}, [dependency1]);
useEffect(() => {
// effect2
return () => {
// cleanup2
};
}, [dependency2]);
示例:
import React, { useState, useEffect } from 'react';
function Clock() {
const [time, setTime] = useState(new Date());
useEffect(() => {
const intervalId = setInterval(() => {
setTime(new Date());
}, 1000);
return () => {
clearInterval(intervalId);
};
}, []);
return <p>The time is {time.toLocaleTimeString()}</p>;
}
export default Clock;
详解:
- 使用多个
useEffect hook 可以为不同的副作用操作定义不同的effect 函数。 - 每个
useEffect hook 都可以定义自己的依赖数组,以控制何时重新运行effect
useEffect hook 的注意事项:
useEffect 函数在组件首次渲染后异步执行。如果在渲染期间需要同步更新状态,请使用useLayoutEffect hook。- 如果
effect 函数不需要清理,请忽略返回函数。 - 如果
effect 函数依赖于组件作用域内的变量,必须将这些变量添加到依赖数组中。 - 如果
effect 函数不需要依赖,将空数组作为依赖数组。 - 如果
effect 函数需要访问props 或state,必须在依赖数组中添加props 或state,以便在effect 函数中访问最新值。 - 如果
effect 函数需要更新state,请使用函数形式的setState,以避免由于异步更新而引起的竞态条件。
总结:useEffect 是 React Hooks 中常用的 hook 之一,它允许您在组件挂载、卸载或更新时执行副作用操作。使用 useEffect,您可以定义副作用操作和清理操作,并控制何时重新运行 effect 函数。您还可以使用多个 useEffect hook 和依赖数组来处理不同的副作用操作和依赖项。在使用 useEffect 时,请注意异步执行、依赖项和状态更新等问题。
useContext
useContext 是一个用于访问 React 上下文的 hook。它接受一个上下文对象,并返回上下文对象中的值。
const value = useContext(MyContext);
useContext 是 React Hooks 中常用的 hook 之一,它允许您在组件中使用全局的状态。以下是 useContext 的全面详解:
基本用法:
const value = useContext(context);
参数说明:
context:React context 对象。
返回值:
value:React context 的当前值。
示例:
import React, { useState, useContext } from 'react';
const ThemeContext = React.createContext('light');
function Toolbar() {
const theme = useContext(ThemeContext);
return (
<div>
<button style={{ background: theme }}>Click me</button>
</div>
);
}
function App() {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme(theme === 'light' ? 'dark' : 'light');
};
return (
<ThemeContext.Provider value={theme}>
<Toolbar />
<button onClick={toggleTheme}>Toggle theme</button>
</ThemeContext.Provider>
);
}
export default App;
useReducer
useReducer 是一个替代 useState 的 hook,它接受一个 reducer 函数和初始状态值,并返回当前状态和一个 dispatch 函数,用于触发状态更新。与 useState 不同,您可以使用 useReducer 来处理更复杂的状态逻辑。
const [state, dispatch] = useReducer(reducer, initialState);
详解:
useContext hook 可以让您在函数组件中使用全局的状态。useContext 接收一个 React context 对象,并返回该 context 的当前值。- 您必须使用
React.createContext 函数创建 context 对象,并使用Context.Provider 组件提供 context 的值。 - 在组件中使用
useContext hook 可以避免将 context 作为props 传递给所有中间组件的麻烦。 - 您可以在同一个应用程序中使用多个 context 对象。
在类组件中使用 useContext:
const value = this.context;
示例:
import React, { Component } from 'react';
const ThemeContext = React.createContext('light');
class Toolbar extends Component {
static contextType = ThemeContext;
render() {
const theme = this.context;
return (
<div>
<button style={{ background: theme }}>Click me</button>
</div>
);
}
}
class App extends Component {
state = { theme: 'light' };
toggleTheme = () => {
this.setState(state => ({ theme: state.theme === 'light' ? 'dark' : 'light' }));
};
render() {
return (
<ThemeContext.Provider value={this.state.theme}>
<Toolbar />
<button onClick={this.toggleTheme}>Toggle theme</button>
</ThemeContext.Provider>
);
}
}
export default App;
详解:
- 在类组件中使用
useContext hook 可以使用static contextType 属性设置 context 对象。 contextType 属性是一个类属性,它可以设置组件的this.context 属性。- 您仍然需要使用
React.createContext 函数创建 context 对象,并使用Context.Provider 组件提供 context 的值。
注意事项:
- 在函数组件中使用
useContext hook 时,请确保 context 对象已经存在于应用程序中,并通过Context.Provider 组件提供值。 - 如果您的组件需要依赖多个 context 对象,请使用多个
useContext hook。 - 如果您使用
useContext hook 访问了 context 对象,请确保使用React.memo函数来缓存组件,以避免不必要的渲染。
总结:useContext 是 React Hooks 中常用的 hook 之一,它允许您在函数组件中使用全局的状态。使用 useContext,您可以在组件中访问 context 对象的当前值。您需要使用 React.createContext 函数创建 context 对象,并使用 Context.Provider 组件提供 context 的值。在类组件中,您可以使用 static contextType 属性设置 context 对象,或者在 render 方法中使用 this.context 属性。在使用 useContext 时,请注意 context 对象是否存在,并通过 Context.Provider 组件提供值。如果您的组件依赖于多个 context 对象,请使用多个 useContext hook。
useCallback
useCallback 是一个用于缓存回调函数的 hook,它接受一个回调函数和一个依赖项数组,并返回一个 memoized 的回调函数。每当依赖项发生变化时,该 hook 将返回一个新的回调函数。
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
useCallback 是 React Hooks 中常用的 hook 之一,它可以用于缓存回调函数以避免在每次渲染时创建新的函数。以下是 useCallback 的全面详解:
基本用法:
const memoizedCallback = useCallback(
() => {
// callback
},
[dependency]
);
参数说明:
callback:要缓存的回调函数。dependency:依赖数组,用于控制何时重新创建回调函数。
返回值:
memoizedCallback:缓存后的回调函数。
示例:
import React, { useState, useCallback } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount(count + 1);
}, [count]);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={handleClick}>Click me</button>
</div>
);
}
export default Counter;
详解:
useCallback hook 可以用于缓存回调函数以避免在每次渲染时创建新的函数。useCallback 接收一个回调函数和一个依赖数组,并返回一个缓存后的回调函数。- 如果依赖数组不为空,则当依赖项更改时,
useCallback 将返回一个新的回调函数。 - 如果依赖数组为空,则
useCallback 将始终返回相同的回调函数。 - 使用
useCallback hook 可以提高应用程序的性能,因为它避免了在每次渲染时创建新的回调函数。
在依赖项不变的情况下缓存回调函数:
const memoizedCallback = useCallback(
() => {
// callback
},
[]
);
示例:
import React, { useState, useCallback } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount(prevCount => prevCount + 1);
}, []);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={handleClick}>Click me</button>
</div>
);
}
export default Counter;
详解:
- 如果依赖数组为空,则
useCallback 将始终返回相同的回调函数。 - 在依赖项不变的情况下缓存回调函数可以提高应用程序的性能,因为它避免了在每次渲染时创建新的回调函数。
- 如果回调函数依赖于状态或
props,则必须将这些值添加到依赖数组中。
注意事项:
-
在使用
useCallback hook 时,请确保只缓存必要的回调函数。 -
如果回调函数没有任何依赖项,则不需要使用
useCallback 进行缓存。 -
如果您在
render 方法中使用箭头函数来定义回调函数,则可能需要使用useCallback -
如果回调函数的依赖项在
props 中定义,则可能需要将React.memo 函数用于组件。
总结: useCallback 是 React Hooks 中常用的 hook 之一,它可以用于缓存回调函数以避免在每次渲染时创建新的函数。使用 useCallback,您可以定义回调函数并指定其依赖项,以控制何时重新创建函数。在依赖项不变的情况下缓存回调函数可以提高应用程序的性能。在使用 useCallback 时,请注意缓存必要的回调函数,并在回调函数依赖于状态或 props 时添加依赖项。如果您在 render 方法中使用箭头函数来定义回调函数,则可能需要使用 useCallback 进行缓存。如果回调函数的依赖项在 props 中定义,则可能需要将 React.memo 函数用于组件。
useMemo
useMemo 是一个用于缓存值的 hook,它接受一个回调函数和一个依赖项数组,并返回一个 memoized 的值。每当依赖项发生变化时,该 hook 将返回一个新的值。
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
useMemo 是 React Hooks 中常用的 hook 之一,它可以用于缓存计算结果以避免在每次渲染时重新计算。以下是 useMemo 的全面详解:
基本用法
const memoizedValue = useMemo(
() => {
// value
},
[dependency]
);
参数说明:
value:要缓存的计算结果。dependency:依赖数组,用于控制何时重新计算计算结果。
返回值:
memoizedValue:缓存后的计算结果。
示例:
import React, { useState, useMemo } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const factorial = useMemo(() => {
console.log('Calculating factorial...');
let result = 1;
for (let i = 1; i <= count; i++) {
result *= i;
}
return result;
}, [count]);
return (
<div>
<p>{count}! = {factorial}</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
export default Counter;
详解:
useMemo hook 可以用于缓存计算结果以避免在每次渲染时重新计算。useMemo 接收一个计算函数和一个依赖数组,并返回一个缓存后的计算结果。- 如果依赖数组不为空,则当依赖项更改时,
useMemo 将重新计算计算结果。 - 如果依赖数组为空,则
useMemo 将始终返回相同的计算结果。 - 使用
useMemo hook 可以提高应用程序的性能,因为它避免了在每次渲染时重新计算结果。
在依赖项不变的情况下缓存计算结果:
const memoizedValue = useMemo(
() => {
// value
},
[]
);
示例:
import React, { useState, useMemo } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const factorial = useMemo(() => {
console.log('Calculating factorial...');
let result = 1;
for (let i = 1; i <= 10; i++) {
result *= i;
}
return result;
}, []);
return (
<div>
<p>{count}! = {factorial}</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
export default Counter;
详解:
- 如果依赖数组为空,则
useMemo 将始终返回相同的计算结果。 - 在依赖项不变的情况下缓存计算结果可以提高应用程序的性能,因为它避免了在每次渲染时重新计算结果。
注意事项:
-
在使用
useMemo hook 时,请确保只缓存必要的计算结果。 -
如果计算结果没有任何依赖项,则不需要使用
useMemo 进行缓存。 -
如果计算结果依赖于状态或
props,则必须将这些值添加到依赖数组中。 -
如果您的计算函数需要访问全局状态,请考虑使用
useCallback 和useMemo。
总结:useMemo 是 React Hooks 中常用的 hook 之一,它可以用于缓存计算结果以避免在每次渲染时重新计算。使用 useMemo,您可以定义计算函数并指定其依赖项,以控制何时重新计算结果。在依赖项不变的情况下缓存计算结果可以提高应用程序的性能。在使用 useMemo 时,请注意缓存必要的计算结果,并在计算结果依赖于状态或 props 时添加依赖项。如果您的计算函数需要访问全局状态,请考虑使用 useCallback 和 useMemo。
useRef
useRef 是一个用于创建可变引用的 hook,它可以用于在组件渲染之间存储数据。它返回一个包含当前值的对象,该值在每次渲染时保持不变。
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus();
}, []);
useRef 是 React Hooks 中常用的 hook 之一,它可以用于创建一个可变的引用,并在组件渲染时保留该引用。以下是 useRef 的全面详解:
基本用法:
const refContainer = useRef(initialValue);
参数说明:
initialValue:初始值。
返回值:
refContainer:一个可变的对象,其中包含current 属性,该属性在组件重新渲染时保持不变。
示例:
import React, { useRef } from 'react';
function TextInput() {
const inputRef = useRef(null);
const handleClick = () => {
inputRef.current.focus();
};
return (
<div>
<input type="text" ref={inputRef} />
<button onClick={handleClick}>Focus</button>
</div>
);
}
export default TextInput;
详解:
useRef hook 可以用于创建一个可变的引用,并在组件渲染时保留该引用。useRef 接收一个初始值,并返回一个包含current 属性的可变对象。ref 属性可以用于引用DOM 元素或组件实例。- 使用
useRef hook 可以提供对DOM 元素或组件实例的引用,从而允许您访问其属性和方法。 ref 属性和useRef hook 都允许您在组件之间共享引用。
示例:
import React, { useState, useRef } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const prevCountRef = useRef();
const handleClick = () => {
prevCountRef.current = count;
setCount(count + 1);
};
const prevCount = prevCountRef.current;
return (
<div>
<p>You clicked {count} times</p>
{prevCount && (
<p>
Previous count: {prevCount}
</p>
)}
<button onClick={handleClick}>Click me</button>
</div>
);
}
export default Counter;
详解:
useRef hook 可以用于在组件之间共享引用。- 在此示例中,我们使用
useState hook 来跟踪计数,并使用useRef hook 来跟踪以前的计数。 - 在每次单击按钮时,我们将当前计数存储在
prevCountRef.current 中,并将计数增加 1。 - 然后,我们使用
prevCountRef.current 显示以前的计数。
注意事项:
-
使用
useRef hook 可以提供对DOM 元素或组件实例的引用,但请确保只在必要时使用它,因为它可能会破坏 React 的组件模型。 -
如果您需要在组件之间共享状态,请使用
useContext 或useReducer。 -
在使用
useRef hook 时,请确保不要将其与ref 属性混淆,因为它们的行为略有不同。 -
ref 属性和useRef hook 都允许您在组件之间共享引用,但是ref 属性更适合用于引用DOM 元素,而useRef hook 更适合用于引用组件实例或其他可变值。
总结:useRef 是 React Hooks 中常用的 hook 之一,它可以用于创建一个可变的引用,并在组件渲染时保留该引用。使用 useRef,您可以获得对 DOM 元素或组件实例的引用,从而允许您访问其属性和方法。ref 属性和 useRef hook 都允许您在组件之间共享引用,但是 ref 属性更适合用于引用 DOM 元素,而 useRef hook 更适合用于引用组件实例或其他可变值。在使用 useRef hook 时,请确保不要将其与 ref 属性混淆,并注意只在必要时使用它,因为它可能会破坏 React 的组件模型。
useImperativeHandle
useImperativeHandle 是一个用于暴露自定义方法的 hook,它允许您在父组件中访问子组件的方法。它接受一个 ref 对象和一个回调函数,该回调函数将返回一个 API 对象,该对象将成为 ref 的当前值。
function ChildComponent(props, ref) {
const inputRef = useRef(null);
useImperativeHandle(ref, () => ({
focusInput: () => {
inputRef.current.focus();
}
}));
return <input type="text" ref={inputRef} />;
}
ChildComponent = forwardRef(ChildComponent);
useLayoutEffect
useLayoutEffect 与 useEffect 类似,它也允许您执行副作用操作。但是,它会在浏览器绘制之前同步执行回调函数,以便可以立即更新 DOM。
useLayoutEffect(() => {
// update DOM synchronously
}, [dependency]);
useDebugValue
useDebugValue 是一个用于调试自定义 Hooks 的 hook。它接受一个格式化函数和一个值,并在 React 开发者工具中显示格式化后的值。
function useCustomHook() {
const [value, setValue] = useState('');
useDebugValue(value, value => `Value: ${value}`);
return [value, setValue];
}
以上是 React Hooks 的全部详解,您可以根据需要选择适合您的 hook 来优化您的 React 组件。