iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 17
2

今天將直接實作 redux,如果不知道 redux 運作概念的讀者可以回去看看昨天的概念介紹喔~
今天嘗試將 dark theme 與 light theme 實作出來,將決定 dark 還是 light 的 state 放在 store 中,讓 component 都可以去 store 抓取,並透過 button 做背景模式的切換。

首先先在專案的 root 創建 actions、reducers、store 三個資料夾,分別存放 redux 三大元素的程式碼,當然你也可以把他們寫在一起,但考慮到專案如果擴大,維護上會很困難,因此還是養成切分檔案的習慣吧!

接著從 action 開始著手吧!
actions 資料夾中 建立 themeAction.js,並輸入:

export const changeTheme = () => {
	return {
		type: 'CHANGE_THEME'
	}
}

這邊使用到 action creator 的概念,將 action 用函式包裝起來,這樣在 dispatch 中只要呼叫這個函式就可以了。因為這次實作的內容比較簡單,我們只需要對 global state 做 true and false 的切換,因此 action 中只需要帶上 type 就好,不需要帶 payload ,也只需要一個 action 就夠了。

接著在 reducers 資料夾中建立 themeReducer.js,並輸入:

const initialState = {
	darkTheme: false
}

const reducer = (state = initialState, action) => {
	switch(action.type) {
		case 'CHANGE_THEME':
			return {
				...state,
				darkTheme: !state.darkTheme
			}
		default:
			return state
	}
}

export default reducer;

reducer 是一個 function ,當 action 被 dispatch 時會發動,第一個參數是 state ,一般上會習慣給他初始值,第二個參數則是 action ,reducer 一般會搭配 switch ,根據不同的 action type 對 state 做操作,我們的範例中只有一個 action type ,所以只需要針對一個 case 做定義,default 值則是在沒有對應 case 時會回傳原有的 state。
特別注意的是一般我們不會直接改變 state 的值,而是重新創建一個 state 物件,以避免不可預期的 bug。
因此才會寫成

return {
	...state,
	darkTheme: !state.darkTheme
}

將目前的 state 的值加進新的物件,並針對要改變的部分改動,最後回傳新的物件當作新的 state

再來是 store 的部分,在 store 資料夾創建 configurestore.js:

import { createStore } from 'redux';
import themeReducer from '../reducers/themeReducer';

export default () => {
    const store  = createStore(
        themeReducer
    )

    return store;
}

這邊非常簡單,從redux 中引入 createStore,並把剛剛創建的 reducer 傳入就可以了
(如果需要傳入多個 reducer 可以使用 applyMiddleware,就交給讀者自行探索了)

最後的最後,回到 react 的最父層 index.js,並改成:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import configureStore from './store/configureStore';
import { Provider } from 'react-redux';

const store = configureStore();

ReactDOM.render(
<Provider store={store}>
	<App />
</Provider>, document.getElementById('root'));

serviceWorker.unregister();

這邊先呼叫剛剛的 configureStore function 建立 store 實體,而要能夠使用 store 中的 state 的元件都必須被包在 react-redux 引入的 Provider 中,包起來後再把 store 實體傳入,我們就做好使用 global state 的準備了。

今天的篇幅比我想像的還要長,因此在 component 中的應用就留到明天了,明天將會介紹使用 redux 的方式,偷偷透露一個好消息,現在使用 redux 的 state 也有 hooks 可以使用囉,變得方便很多,明天見囉!


上一篇
【Day 16】state management - redux 基礎概念
下一篇
【Day 18】Redux 實戰演練(2)
系列文
React.js 從 【0】 到【1】推坑計畫 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
神Q超人
iT邦研究生 5 級 ‧ 2019-09-21 13:42:36

有考慮過把 action.type 'CHANGE_THEME' 變成一個常數管理嗎?像這樣子:

const CHANGE_THEME = 'CHANGE_THEME';

就不怕說有可能會在 action 和 reducer 之間打錯字 XD

平常會這樣做,因為想說只有一個 action 就沒有採用這個方法,但還是感謝提醒!

神Q超人 iT邦研究生 5 級 ‧ 2019-09-22 11:25:16 檢舉

嘿嘿!只是疑惑會不會有不同派別 XD

我要留言

立即登入留言