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