iT邦幫忙

2021 iThome 鐵人賽

DAY 23
0
Modern Web

Follow me! 來一場前端技能樹之旅系列 第 23

[Day 23 - Redux] React + Redux = React-redux

  • 分享至 

  • xImage
  •  

前情提要:在前面的文章有了Redux,狀態管理沒煩惱,學到了如何在 Redux 透過 Action 管理更新所有的 State。接下來就讓我們學習如何在 React 中使用 Redux 來處理資料狀態。

Redux 是一個獨立的狀態管理函式庫,它可以搭配原生 Javascript 直接撰寫出一個應用程式,也可以與其他框架像是 React、Angular 一起運作。而當 Redux 與 React 結合時,會使用 React-redux 這個延伸的函式庫,有效的來解決 React Component 間 State 複雜化的問題

安裝React-redux

Fork 一份之前所使用的React - 計時器範例程式碼,基於這個架構從頭來使用 React-redux。

React-redux 前面建置步驟基本上跟單純使用 Redux 一樣,要事先建立 Action、Reducer、Store,所以我們直接貼上前篇建立好的三份程式碼 actions.js、reducer.js、store.js,裡面包含了 Redux 應用在計數器的內容。

actions.js

export const ADD_SCORE = "ADD_SCORE";
export const REDUCE_SCORE = "REDUCE_SCORE";

// action creator
export function addScore(idx) {
  return {
    type: ADD_SCORE,
    payload: { idx }
  };
}

export function reduceScore(idx) {
  return {
    type: REDUCE_SCORE,
    payload: { idx }
  };
}

reducer.js

import { ADD_SCORE, REDUCE_SCORE } from "./actions";

const initialState = {
  members: [
    { name: "May", score: 0 },
    { name: "Julia", score: 0 },
    { name: "Selina", score: 0 }
  ]
};

export default function appReducer(state = initialState, action) {
  switch (action.type) {
    case ADD_SCORE: {
      let new_members = state.members;
      new_members[action.payload.idx] = {
        ...new_members[action.payload.idx],
        score: new_members[action.payload.idx].score + 1
      };
      return {
        members: new_members
      };
    }
    case REDUCE_SCORE: {
      let new_members = state.members;
      new_members[action.payload.idx] = {
        ...new_members[action.payload.idx],
        score: new_members[action.payload.idx].score - 1
      };
      return {
        members: new_members
      };
    }
    default:
      return state;
  }
}

store.js

import { createStore } from "redux";
import rootReducer from "./reducer";

const store = createStore(rootReducer);

export default store;

傳遞 Store

接著就讓我們正式將 React 與 Redux 結合,我們首先要做的就是讓 React Component 知道 Store,才能讀取資料和調用動作,所以就透過在 Root component 使用 <Provider> 的方式來傳遞 Store。

...
import { Provider } from "react-redux";
import store from './store'

ReactDOM.render(
  <StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </StrictMode>,
  rootElement
);

從 Store 讀取狀態

要從 Store 讀取狀態,可以使用 useSelector 這個方法,直接提取 Redux Store 中的狀態數據到指定的元件中。並且它會對之前的選擇器回傳值和當前的回傳值進行比較,如果不同,相關的組件就會重新渲染。

App.js

import { useSelector } from "react-redux";

export default function App() {
  const members = useSelector((state) => state.members);

  return (
    <div className="App">
      ...
      {members.map((member) => (
        <Member key={member.name} idx={index} />
      ))}
    </div>
  );
}

Member.js

...
import { useSelector } from "react-redux";

export default function Member(props) {
  const members = useSelector((state) => state.members);

  return (
    <div className="member">
      <h2>{members[props.idx].name}</h2>
      <div>{members[props.idx].score > 0 ? "PASS" : "FAIL"}</div>
      <Counter idx={props.idx} />
    </div>
  );
}

Counter.js

import { useDispatch, useSelector } from "react-redux";
import { addScore, reduceScore } from "../actions";

export default function Counter(props) {
  const score = useSelector((state) => state.members[props.idx].score);

  return (
    <div className="Counter">
      <h3>{score}</h3>
      ...
      {score > 0 && (
        <button>minus</button>
      )}
    </div>
  );
}

調用動作

完成從 Store 讀取資料狀態後,最後一個步驟就是要可以在組件中調用動作,來修改 State 的值。我們可以透過 useDispatch() 這個方法,發動指定的 Action 到 Reducer 中更新 State。

Counter.js

...
import { useDispatch, useSelector } from "react-redux";
import { addScore, reduceScore } from "../actions";

export default function Counter(props) {
  const score = ...
  const dispatch = useDispatch();

  return (
    <div className="Counter">
      ...
      <button onClick={() => dispatch(addScore(props.idx))}>Plus</button>
      {score > 0 && (
        <button onClick={() => dispatch(reduceScore(props.idx))}>minus</button>
      )}
    </div>
  );
}


小結

在 React 中使用 Redux 的 React-redux 基本上就是這樣運作的,以往在 React 中需要透過提升 State 層級才能在 Component 間共同使用狀態,結合 Redux 集中狀態管理的功能,就能有效的管理複雜的 State,彌補了 React 框架的缺點更提升它的優勢。

範例程式碼

如果文章中有錯誤的地方,要麻煩各位大大不吝賜教;喜歡的話,也要記得幫我按讚訂閱喔❤️

參考資料


上一篇
[Day 22 - Redux] 有了Redux,狀態管理沒煩惱
下一篇
[Day 24 - Modern CSS] 在JS中寫CSS,神套件Styled-components
系列文
Follow me! 來一場前端技能樹之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言