一個最常見的作法。
簡述
雖然說你也可以自己手動把 Redux 跟 React 給串起來,但透過套件來處理會更好。這邊會介紹一套叫做 react-redux 的 library,用它來把 React 跟 Redux 串接起來。
記得,redux 跟 react-redux 是不同的東西:
- Redux 是管理狀態的 library
- react-redux 是用來把 React 跟 redux 結合起來的 library
不要再搞混啦!
要用 react-redux 的方式 有兩種,一種是建立 create-react-app 時加上參數:
| 1
 | npx create-react-app my-app --template redux
 | 
一種是對現有的 create-react-app 來加上 react-redux:
| 12
 
 | npm install redux npm install react-redux
 
 | 
我們要介紹的是第二種。
基本的資料夾結構
在串接之前記得先做好 redux 前置作業,你的資料夾結構應該會長成這樣:
- redux
- reducers
- todos.js
- users.js
- index.js (把所有 reducer 集合起來)
 
- store.js(負責建立 store)
- actionTypes.js(把 action type 的常數集合起來)
- actions(action creator 管理)
- selectors(把選出 state 的 function 集合起來)
 
這邊列出我覺得需要知道一下內容的幾個檔案:
1. reducers/index.js
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | import { combineReducers } from "redux";import todosReducer from "./todos"
 import usersReducer from "./users"
 
 
 export default combineReducers({
 todosReducer,
 usersReducer
 })
 
 | 
這邊因為是「多個」reducer,所以資料結構會跟只有「單一個」的時候不太一樣,要多注意一下。
單一個的時候:
| 12
 
 | const store = createStore(todosReducer);console.log(store.getState());
 
 | 
output:
| 12
 3
 
 | {todos: ['todo1', 'todo2', 'todo3']
 }
 
 | 
多個的時候:
| 12
 
 | const store = createStore(todosReducer);console.log(store.getState());
 
 | 
output:
| 12
 3
 4
 5
 6
 7
 8
 
 | {todosReducer: {
 todos: ['todo1', 'todo2']
 },
 usersReducer: {
 users: ['user1', 'user2']
 }
 }
 
 | 
2. redux/store.js
| 12
 3
 4
 5
 
 | import { createStore } from "redux";import rootReducer from "./reducers";
 
 
 export default createStore(rootReducer);
 
 | 
3. redux/selectors.js
這邊做個補充,selector 的用途只是「把我想要的 state 選出來」而已,畢竟你應該不會想在一個 Component 裡面拿到所有的 state,所以才會衍伸出這個東西。
另外之所以會抽出去建立成 constant 只是因為 code 寫起來會比較簡潔而已。 
| 12
 3
 
 | export const selectTodos = state => state.todosReducer.todos;
 export const selectUsers = state => state.usersReducer.users;
 
 | 
其他的就只是把原本的東西抽出去寫成一個檔案而已,忘記的話可以參考:初探 Redux
正式串接
這邊寫個懶人包:
- 定義 Provider
- 把 store傳入Provider,讓底下所有元件能夠接收
- 在元件內使用 useSelector取出需要的 state(搭配前面寫好的 selectors.js)
- 先引入 useDispatch,接著就能透過dispatch發出action
這邊直接附上 code,你邊看邊想一下應該就懂了:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | import { Provider } from "react-redux";
 import store from "./redux/store"
 
 const root = ReactDOM.createRoot(document.getElementById("root"));
 root.render(
 <Provider store={store}>
 <App />
 </Provider>
 );
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 
 | import { useState, useEffect } from "react";
 import { useSelector, useDispatch } from "react-redux";
 import { selectTodos } from "./redux/selectors"
 import { addTodo } from "./redux/actions"
 
 function App() {
 const [value, setValue] = useState("");
 
 const todos = useSelector(selectTodos);
 
 const dispatch = useDispatch();
 
 
 const handleSubmit = e => {
 e.preventDefault();
 dispatch(addTodo(value));
 setValue("")
 }
 
 return (
 <div className="App">
 <form onSubmit={handleSubmit}>
 <input value={value} onChange={e => setValue(e.target.value)} />
 </form>
 <ul>
 {todos.map(todo => <li key={todo.id} data-id={todo.id} >{todo.name}</li>)}
 </ul>
 </div>
 );
 }
 
 export default App;
 
 | 
這樣子其實就串好囉!有疑問的話也可以去我寫的 範例 參考。