面试题答案
一键面试初始化与更新机制的细微差异
- 初始化:
- 普通函数式组件中
useState
:初始化值在首次渲染时被使用,如果初始值是一个函数,该函数只会在组件挂载时执行一次。例如:
import React, { useState } from'react'; const MyComponent = () => { const [count, setCount] = useState(() => { console.log('Initializing count'); return 0; }); return <div>{count}</div>; };
- 自定义Hook中
useState
:初始化逻辑同样在首次调用自定义Hook时执行。不过,自定义Hook可能在多个组件中被使用,每个使用它的组件都会独立初始化其内部的useState
。例如:
import React, { useState } from'react'; const useMyHook = () => { const [value, setValue] = useState(() => { console.log('Initializing value in custom hook'); return 'default value'; }); return { value, setValue }; }; const ComponentA = () => { const { value, setValue } = useMyHook(); return <div>{value}</div>; }; const ComponentB = () => { const { value, setValue } = useMyHook(); return <div>{value}</div>; };
- 普通函数式组件中
- 更新:
- 普通函数式组件中
useState
:直接调用setState
函数更新状态,React会对比新老状态,决定是否重新渲染组件。例如:
import React, { useState } from'react'; const MyComponent = () => { const [count, setCount] = useState(0); const increment = () => { setCount(count + 1); }; return ( <div> <button onClick={increment}>Increment</button> <p>{count}</p> </div> ); };
- 自定义Hook中
useState
:更新机制本质相同,但由于自定义Hook可能封装了更复杂的逻辑,可能需要额外注意状态更新的触发时机。例如,如果自定义Hook内部有副作用依赖于状态更新,需要正确处理依赖数组。
import React, { useState, useEffect } from'react'; const useMyHook = () => { const [data, setData] = useState(null); useEffect(() => { if (data) { // 模拟一些副作用操作,如数据处理 console.log('Processing data:', data); } }, [data]); return { data, setData }; }; const MyComponent = () => { const { data, setData } = useMyHook(); const fetchData = () => { setData('new data'); }; return ( <div> <button onClick={fetchData}>Fetch Data</button> {data && <p>{data}</p>} </div> ); };
- 普通函数式组件中
在自定义Hook中优化State的更新
- 避免不必要的渲染:
- 使用
useCallback
和useMemo
:在自定义Hook返回的函数或值可能导致不必要渲染时,使用useCallback
和useMemo
进行优化。例如:
import React, { useState, useCallback, useMemo } from'react'; const useMyHook = () => { const [count, setCount] = useState(0); const increment = useCallback(() => { setCount(count + 1); }, [count]); const doubleCount = useMemo(() => { return count * 2; }, [count]); return { count, increment, doubleCount }; }; const MyComponent = () => { const { count, increment, doubleCount } = useMyHook(); return ( <div> <button onClick={increment}>Increment</button> <p>Count: {count}</p> <p>Double Count: {doubleCount}</p> </div> ); };
- 使用
- 处理副作用以避免内存泄漏:
- 正确使用
useEffect
的清理函数:如果自定义Hook中有副作用(如订阅事件、定时器等),需要在组件卸载时清理。例如:
import React, { useState, useEffect } from'react'; const useMyHook = () => { const [isVisible, setIsVisible] = useState(false); useEffect(() => { const eventListener = () => { console.log('Window resize event'); }; window.addEventListener('resize', eventListener); return () => { window.removeEventListener('resize', eventListener); }; }, []); return { isVisible, setIsVisible }; }; const MyComponent = () => { const { isVisible, setIsVisible } = useMyHook(); return ( <div> <button onClick={() => setIsVisible(!isVisible)}>Toggle Visibility</button> {isVisible && <p>Content is visible</p>} </div> ); };
- 正确使用
通过上述方式,可以在自定义Hook中合理优化State的更新,提高性能并避免内存泄漏等问题。