面試官:React-Redux 它是怎么更新界面的?

react-redux 的核心是 訂閱 store 變化 并 觸發(fā)組件重新渲染。它利用 React 的 context 和 useSyncExternalStore 來(lái)高效地管理狀態(tài)和 UI 更新。下面詳細(xì)講解 react-redux 是如何更新界面的。
react-redux 更新 UI 的流程
- **組件連接 Redux store**(Provider 共享全局狀態(tài))
 - 組件訂閱 store 變化(useSelector / connect 監(jiān)聽(tīng)數(shù)據(jù)變化)
 - **狀態(tài)改變時(shí),觸發(fā) store.subscribe**(Redux dispatch 觸發(fā) store 更新)
 - 對(duì)比新舊狀態(tài),決定是否重新渲染(避免不必要的 UI 更新)
 - 通知組件重新渲染(React useState 或 forceUpdate 觸發(fā)渲染)
 
1. Redux store 如何連接到 React
在 react-redux 中,我們通過(guò) Provider 讓整個(gè)應(yīng)用訪問(wèn) store:
import { Provider } from "react-redux";
import { store } from "./store";
export default function App() {
  return (
    <Provider store={store}>
      <MyComponent />
    </Provider>
  );
}- Provider 使用 React Context 傳遞 store。
 - 子組件可以用 useSelector 訪問(wèn) Redux 狀態(tài)。
 
2. 組件如何訂閱 Redux 狀態(tài)
組件可以使用 useSelector 訂閱 store 里的狀態(tài):
import { useSelector } from "react-redux";
function MyComponent() {
  const count = useSelector(state => state.counter.value);
  return <p>Count: {count}</p>;
}useSelector 如何監(jiān)聽(tīng)狀態(tài)變化?
- useSelector 內(nèi)部會(huì)調(diào)用 store.subscribe() 訂閱 Redux store 變化
 - 當(dāng) dispatch 修改 store 時(shí),所有 useSelector 訂閱的組件都會(huì)執(zhí)行
 - useSelector 會(huì)對(duì)比新舊狀態(tài)(默認(rèn)用 === 淺比較)
 - 如果狀態(tài)沒(méi)變,組件不會(huì)重新渲染,避免不必要的更新
 
3. Redux dispatch 如何觸發(fā) UI 更新
組件通過(guò) dispatch 觸發(fā) Redux store 更新:
import { useDispatch } from "react-redux";
import { increment } from "./counterSlice";
function MyComponent() {
  const dispatch = useDispatch();
  return <button onClick={() => dispatch(increment())}>+1</button>;
}dispatch 更新流程
- dispatch(action) 觸發(fā) Redux store 更新
 - Redux reducer 計(jì)算新 state
 - store 觸發(fā) store.subscribe() 通知所有 useSelector 訂閱的組件
 - useSelector 比較狀態(tài),如果變化則觸發(fā)組件 重新渲染
 
4. react-redux 內(nèi)部是如何訂閱 store 的?
useSelector 的底層實(shí)現(xiàn)
在 react-redux 中,useSelector 用 useSyncExternalStore 監(jiān)聽(tīng) store:
import { useSyncExternalStore } from "react";
function useSelector(selector) {
  const store = useContext(StoreContext);
  return useSyncExternalStore(
    store.subscribe,      // 訂閱 Redux store
    () => selector(store.getState()) // 獲取最新?tīng)顟B(tài)
  );
}useSyncExternalStore 如何工作?
- **訂閱 
store**(store.subscribe) - 檢測(cè)狀態(tài)是否變化(通過(guò) 
store.getState()獲取最新值) - 如果狀態(tài)變了,觸發(fā)組件重新渲染(React 重新執(zhí)行組件)
 
Redux 更新 UI 的完整流程
- dispatch(action) 觸發(fā) store 更新
 - reducer 計(jì)算新 state
 - store 調(diào)用 store.subscribe() 通知組件
 - 組件的 useSelector 重新執(zhí)行,并對(duì)比狀態(tài)
 - 如果狀態(tài)變化,則 觸發(fā) React 重新渲染
 
react-redux UI 更新的優(yōu)化
1. 避免不必要的渲染
- useSelector 只會(huì)讓組件更新受影響的狀態(tài),而不是整個(gè) store。
 - 默認(rèn)使用 === 淺比較,確保狀態(tài)真的變化才會(huì)觸發(fā)渲染:
 
const value = useSelector(state => state.value, (a, b) => a === b);- 如果 useSelector 依賴(lài)對(duì)象,可以使用 reselect 進(jìn)行 Memoization。
 
2. 使用 useCallback 和 useMemo
- useDispatch() 生成的 dispatch 函數(shù)不會(huì)變,但 useSelector 可能導(dǎo)致組件重新渲染:
 
const data = useMemo(() => expensiveCalculation(state), [state]);
const handleClick = useCallback(() => dispatch(increment()), [dispatch]);3. 代碼分片(Lazy Load)
- 使用 redux-toolkit 的 lazyReducerEnhancer 進(jìn)行動(dòng)態(tài)加載 reducer,減少初始化開(kāi)銷(xiāo)。
 
總結(jié)
步驟  | React Redux UI 更新流程  | 
1. 組件連接 store  | Provider 通過(guò) Context 提供 Redux store  | 
2. 組件訂閱狀態(tài)  | useSelector 監(jiān)聽(tīng) store 變化  | 
3. 狀態(tài)變更  | dispatch 觸發(fā) store 更新  | 
4. 組件重新渲染  | useSyncExternalStore 檢測(cè)狀態(tài)變更,觸發(fā) UI 更新  | 
5. 性能優(yōu)化  | useSelector 只更新受影響的組件,減少不必要渲染  | 
React-Redux 通過(guò) useSelector 監(jiān)聽(tīng) store,dispatch 觸發(fā) store 變更,useSyncExternalStore 檢測(cè) state 變化,決定是否重新渲染組件,從而實(shí)現(xiàn)高效的 UI 更新。















 
 
 







 
 
 
 