loading...
上次更新: 2024-06-11
Demo: https://codesandbox.io/p/sandbox/redux-11-react-redux-zmn3l6
Demo 說明:
畫面上顯示蛋糕數量,和 'Order cake' 以及 'Restock cake' 兩個按鈕。
點擊 'Order cake',數量會減一。
點擊 'Restock cake',數量會加五。
在這章節,終於要進入 react-redux 了。
React 中使用 Redux,我們會使用 Redux-toolkit 來幫忙建立 slice 和 store,方式就跟前面章節說明的一樣,差別只在於前面章節是在 node.js 環境跑,這次是在瀏覽器環境,因此可使用 import。slice 和 store,並且示範在 react-redux 要如何取得 state 和發送 action 來更新 state。npx create-react-app my-app
react-reduxyarn add react-redux
或
npm install react-redux
redux-toolkityarn add @reduxjs/toolkit
或
npm install @reduxjs/toolkit
在 src/features/cake/cakeSlice.js
// 引入 createSlice
import { createSlice } from '@reduxjs/toolkit';
// createSlice 接收一個物件,此物件包含三個參數
const cakeSlice = createSlice({
name: 'cake',
initialState: {
numOfCakes: 10,
},
reducers: {
order: (state, action) => {
state.numOfCakes -= 1;
},
restock: (state, action) => {
state.numOfCakes += action.payload;
},
},
});
export default cakeSlice.reducer;
export const { order, restock } = cakeSlice.actions;在 src/app/store.js
import { configureStore } from '@reduxjs/toolkit';
import cakeReducer from '../features/cake';
const store = configureStore({
reducer: {
cake: cakeReducer,
},
});
export default store;在 src/components/Cake.jsx
export function Cake() {
return (
<>
<h1>Cake</h1>
<div>Cake 數量:</div>
<button>Order Cake</button>
<button>Restock Cake</button>
</>
);
}在 src/App.js 裡引入 <Cake/> 元件
import { Cake } from './components/Cake';
import './styles.css';
export default function App() {
return (
<div className="App">
<Cake />
</div>
);
}下一步,要讓我們的 React 應用程式能夠讀取 store,這時候就需要用到 react-redux 的 <Provider/>。
src/index.js 引入 Provider 並包住 <App/>store 作為 props 傳入 Providerimport { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { Provider } from 'react-redux';
import store from './app/store';
import App from './App';
const rootElement = document.getElementById('root');
const root = createRoot(rootElement);
root.render(
<StrictMode>
// 用 Provider 包住 App,並傳入 store
<Provider store={store}>
<App />
</Provider>
</StrictMode>,
);在 <Cake/> 元件中,要如何得到存放在 cakeSlice.js 中的 state 呢?
react-redux 的 useSelector hook。useSelector 接收一個函式作為參數,這個函稱式為 selector functionstate 引數,並且要回傳一個值useSelector 會回傳 selector function 所回傳的值// 引入 useSelector
import { useSelector } from 'react-redux';
export function Cake() {
const cakeCount = useSelector(
// 裡面這個函式就是 selector function
(state) => {
// 回傳蛋糕數量
return state.cake.numOfCakes;
},
);
return (
<>
<h1>Cake</h1>
<div>Cake 數量: {cakeCount}</div>
<button>Order Cake</button>
<button>Restock Cake</button>
</>
);
}引入 action creator
複習:記得嗎,action creator 會回傳一個 action,例如:
// action creator
restock(5);會回傳
// action
{
type: 'cake/restock',
payload: 5
}使用 react-redux 的 useDispatch hook,它會回傳 redux store 的 dispatch function
像在前面 redux-toolkit,若要發送 action,我們會這樣寫
store.dispatch(action 放這);在這裡用了 useDispatch,就可直接使用 disaptch(),前面不必再加上 store.
// 引入 useDispatch
import { useSelector, useDispatch } from 'react-redux';
// 引入 action creator
import { order, restock } from '../features/cakes/cakeSlice';
export function Cake() {
const cakeCount = useSelector((state) => {
return state.cake.numOfCakes;
});
const disaptch = useDispatch();
return (
<>
<h1>Cake</h1>
<div>Cake 數量: {cakeCount}</div>
<button
onClick={() => {
disaptch(order());
}}
>
Order Cake
</button>
<button
onClick={() => {
disaptch(restock(5));
}}
>
Restock Cake
</button>
</>
);
}