面试题答案
一键面试1. 使用 useReducer
设计状态管理方案
- 定义初始状态和action类型
- 首先确定共享状态的初始值。例如,假设共享状态包含用户信息、购物车商品列表等:
const initialState = { user: null, cart: [] }; const ActionTypes = { SET_USER: 'SET_USER', ADD_TO_CART: 'ADD_TO_CART', REMOVE_FROM_CART: 'REMOVE_FROM_CART' };
- 编写自定义reducer函数
- 自定义reducer函数根据不同的action类型来处理状态更新。对于复杂的更新逻辑,可以在reducer中进行详细的业务判断。
const sharedReducer = (state, action) => { switch (action.type) { case ActionTypes.SET_USER: return {...state, user: action.payload }; case ActionTypes.ADD_TO_CART: return { ...state, cart: [...state.cart, action.payload] }; case ActionTypes.REMOVE_FROM_CART: return { ...state, cart: state.cart.filter(item => item.id!== action.payload.id) }; default: return state; } };
- 在组件中使用
useReducer
- 在需要共享状态的组件中,通过
useReducer
来获取状态和dispatch函数。
import React, { useReducer } from'react'; const MyComponent = () => { const [sharedState, dispatch] = useReducer(sharedReducer, initialState); return ( <div> {/* 组件内容,可使用 sharedState 和 dispatch */} </div> ); };
- 在需要共享状态的组件中,通过
2. 结合中间件处理异步操作
- 自定义中间件(类似redux - thunk)
- 中间件可以在action被dispatch到reducer之前进行拦截和处理,例如处理异步操作。
const asyncMiddleware = store => next => action => { if (typeof action === 'function') { return action(store.dispatch, store.getState); } return next(action); };
- 应用中间件
- 创建一个增强版的dispatch函数,将中间件应用到dispatch流程中。
const enhancedDispatch = (dispatch, middlewares) => { middlewares.forEach(middleware => { dispatch = middleware({ dispatch, getState: () => sharedState })(dispatch); }); return dispatch; }; const middlewares = [asyncMiddleware]; const enhanced = enhancedDispatch(dispatch, middlewares);
- 使用增强后的dispatch处理异步操作
- 例如,在异步获取用户信息并更新状态时:
const fetchUser = () => { return async (dispatch, getState) => { try { const response = await fetch('/api/user'); const user = await response.json(); dispatch({ type: ActionTypes.SET_USER, payload: user }); } catch (error) { console.error('Error fetching user:', error); } }; }; // 在组件中调用 enhanced(fetchUser());
3. 精细化性能调优
- 使用
React.memo
或shouldComponentUpdate
- 对于只依赖共享状态部分数据的组件,可以使用
React.memo
(对于函数组件)或shouldComponentUpdate
(对于类组件)来避免不必要的重新渲染。 - 例如,对于一个只依赖购物车商品数量的组件:
const CartItemCountComponent = React.memo(({ sharedState }) => { return <div>Cart item count: {sharedState.cart.length}</div>; });
- 对于只依赖共享状态部分数据的组件,可以使用
- 减少不必要的状态更新
- 在reducer中,确保只有当状态真正发生变化时才返回新的状态对象。例如,使用
Object.is
来比较新旧状态,避免不必要的浅拷贝。
const sharedReducer = (state, action) => { let newState; switch (action.type) { case ActionTypes.SET_USER: if (Object.is(state.user, action.payload)) { return state; } newState = {...state, user: action.payload }; return newState; // 其他action类型同理 default: return state; } };
- 在reducer中,确保只有当状态真正发生变化时才返回新的状态对象。例如,使用
- 使用
useCallback
和useMemo
useCallback
用于缓存函数,避免不必要的函数重新创建,例如缓存dispatch函数:
const MyComponent = () => { const [sharedState, dispatch] = useReducer(sharedReducer, initialState); const memoizedDispatch = useCallback(dispatch, []); return ( <div> {/* 使用 memoizedDispatch */} </div> ); };
useMemo
用于缓存计算结果,例如缓存复杂的购物车总价计算:
const CartTotalComponent = ({ sharedState }) => { const total = useMemo(() => { return sharedState.cart.reduce((acc, item) => acc + item.price, 0); }, [sharedState.cart]); return <div>Cart total: {total}</div>; };