1. React 函数式组件的特点
- 使用普通的 JavaScript 函数定义组件。
- 直接返回 JSX。
- 通过 Hooks 管理状态和副作用。
- 代码更简洁,易于维护。
2. React Hooks 的作用
Hooks 是 React 16.8 引入的特性,用于在函数式组件中管理状态和副作用。
常用 Hooks:
useState:用于在函数组件中管理状态。
const [count, setCount] = useState(0);
useEffect:用于处理副作用(如数据获取、订阅、DOM 操作)。
useEffect(() => { console.log('Component mounted or updated'); return () => { console.log('Component will unmount'); }; }, []);
useContext:用于在组件树中共享数据。
const value = useContext(MyContext);
useRef:用于保存可变值或访问 DOM 元素。
const inputRef = useRef(null);
useMemo 和 useCallback:用于性能优化,缓存值和函数。
3. useState 和 useReducer 的区别
useState:
- 适用于简单的状态管理。
- 直接设置状态值。
const [count, setCount] = useState(0);
useReducer:
- 适用于复杂的状态逻辑。
- 通过 reducer 函数管理状态。
const [state, dispatch] = useReducer(reducer, initialState);
4. useEffect 的依赖数组
空数组
[]
:只在组件挂载和卸载时执行。useEffect(() => { console.log('Component mounted'); return () => { console.log('Component unmounted'); }; }, []);
包含依赖的数组
[dep1, dep2]
:在依赖变化时执行。useEffect(() => { console.log('Dependency changed'); }, [dep1, dep2]);
无依赖数组:每次渲染后都执行。
useEffect(() => { console.log('Rendered'); });
5. React 中的 key 属性
作用:帮助 React 识别哪些元素发生了变化,用于优化列表渲染。
示例:
const items = [{ id: 1, name: 'Apple' }, { id: 2, name: 'Banana' }]; return ( <ul> {items.map(item => ( <li key={item.id}>{item.name}</li> ))} </ul> );
6. React.memo 的作用
作用:用于优化函数式组件的渲染性能,避免不必要的重新渲染。
示例:
const MyComponent = React.memo(function MyComponent(props) { return <div>{props.value}</div>; });
7. useCallback 和 useMemo 的区别
useCallback:缓存函数,避免每次渲染都创建新的函数。
const handleClick = useCallback(() => { console.log('Clicked'); }, []);
useMemo:缓存计算结果,避免重复计算。
const expensiveValue = useMemo(() => { return computeExpensiveValue(a, b); }, [a, b]);
8. React 中的 Context API
作用:用于在组件树中共享数据,避免层层传递 props。
示例:
const MyContext = React.createContext(); function App() { return ( <MyContext.Provider value="Hello"> <ChildComponent /> </MyContext.Provider> ); } function ChildComponent() { const value = useContext(MyContext); return <div>{value}</div>; }
9. React 中的 Fragment
作用:用于在不引入额外 DOM 节点的情况下包裹多个元素。
示例:
function MyComponent() { return ( <> <div>Item 1</div> <div>Item 2</div> </> ); }
10. React 中的 Portals
作用:将子组件渲染到 DOM 树中的其他位置。
示例:
function Modal({ children }) { return ReactDOM.createPortal( <div className="modal">{children}</div>, document.getElementById('modal-root') ); }
11. React 中的错误边界(Error Boundaries)
作用:捕获子组件中的 JavaScript 错误,并显示备用 UI。
示例:
class ErrorBoundary extends React.Component { state = { hasError: false }; static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, errorInfo) { console.error('Error:', error, errorInfo); } render() { if (this.state.hasError) { return <div>Something went wrong.</div>; } return this.props.children; } }
12. React 中的懒加载(React.lazy 和 Suspense)
作用:用于延迟加载组件,优化性能。
示例:
const LazyComponent = React.lazy(() => import('./LazyComponent')); function App() { return ( <React.Suspense fallback={<div>Loading...</div>}> <LazyComponent /> </React.Suspense> ); }
13. React 中的性能优化
- 使用
React.memo
:避免不必要的重新渲染。 - 使用
useCallback
和useMemo
:缓存函数和计算结果。 - 懒加载组件:使用
React.lazy
和Suspense
。 - 虚拟化长列表:使用
react-window
或react-virtualized
。
14. React 中的单向数据流
- 概念:数据从父组件流向子组件,子组件通过 props 接收数据。
- 优点:数据流清晰,易于调试和维护。
15. React 中的受控组件和非受控组件
受控组件:表单数据由 React 状态管理。
function ControlledComponent() { const [value, setValue] = useState(''); return <input value={value} onChange={(e) => setValue(e.target.value)} />; }
非受控组件:表单数据由 DOM 自身管理。
function UncontrolledComponent() { const inputRef = useRef(null); return <input ref={inputRef} defaultValue="Hello" />; }