iT邦幫忙

2021 iThome 鐵人賽

DAY 15
1
Modern Web

用30天更加認識 React.js 這個好朋友系列 第 15

Day15-Redux 篇-實作範例

在今天的文章中,我們將會使用 Redux 去完成一個計數器的範例程式。

第一步

使用 createStore 建立一個 Redux store ,並將 store 用 react-redux 的 Provider 元件提供給 React 的母元件 App

// store/index.js
import { createStore } from 'redux';

const counterReducer = (state = { counter: 0 }, action) => {
  if (action.type === 'increment') {
    return { counter: state.counter + 1 };
  }

  if (action.type === 'decrement') {
    return { counter: state.counter - 1 };
  }

  return state;
};

const store = createStore(counterReducer);

export default store;
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';

import App from './App';
import store from './store/index';

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

第二步

在元件使用 useSelector 和 useDispatch 這兩個 hook ,這邊介紹一下這兩個 hook 的用法:

useSelector

使用這個 hook 可以從 store 裡面去拿取想要的 state 出來,效用大致等於 connect 元件的 mapStateToProps。

ex:
const counter = useSelector(state => state.counter);

特點:

  1. 可以返回各種型別的值
  2. useSelector 回傳的值(也就是取出的 state)若有更新,就會重新渲染元件
  3. 不接受 ownProps 參數,但可以透過 JavaScript 的閉包觀念取得元件中的 props

useDispatch

透過這個 hook 會回傳一個 dispatch 方法,可以讓我們 dispatch actions,用來取代 mapStateToDispatch。

const dispatch = useDispatch();

useStore

另外還有一個 hook useStore,不過我們暫時不會用到,但還是介紹一下,它可以取得 store,並進行 getState()、subscribe() 、dispatch() 等函式呼叫。

const store = useStore();

在程式碼中可以看到使用 useSelector 去取出 store 裡面的 counter state,並透過 useDispatch 回傳的 dispatch 方法去觸發 reducer。

// Counter.js
import { useSelector, useDispatch } from "react-redux";

const Counter = () => {
  const dispatch = useDispatch();
  const counter = useSelector((state) => state.counter);

  const incrementHandler = () => {
    dispatch({ type: "increment" });
  };

  const decrementHandler = () => {
    dispatch({ type: "decrement" });
  };

  return (
    <>
      <div>{counter}</div>
      <button onClick={incrementHandler}>Increment</button>
      <button onClick={decrementHandler}>Decrement</button>
    </>
  );
};

export default Counter;

完成以上程式碼的實作後,就可以點擊按鈕做加減了。

3. 增加多一點 state

接著我們多加一個 toggle 按鈕及一個點擊一次就增加多個數字的按鈕。

// store/index.js
import { createStore } from 'redux';

const initialState = { counter: 0, showCounter: true };

const counterReducer = (state = initialState, action) => {
  if (action.type === 'increment') {
    return {
      counter: state.counter + 1,
      showCounter: state.showCounter
    };
  }

  if (action.type === 'increase') {
    return {
      counter: state.counter + action.amount,
      showCounter: state.showCounter
    };
  }

  if (action.type === 'decrement') {
    return {
      counter: state.counter - 1,
      showCounter: state.showCounter
    };
  }

  if (action.type === 'toggle') {
    return {
      showCounter: !state.showCounter,
      counter: state.counter
    };
  }

  return state;
};

const store = createStore(counterReducer);

export default store;
// Counter.js
import { useSelector, useDispatch } from "react-redux";

const Counter = () => {
  const dispatch = useDispatch();
  const counter = useSelector((state) => state.counter);
  const show = useSelector((state) => state.showCounter);

  const incrementHandler = () => {
    dispatch({ type: "increment" });
  };

  const increaseHandler = () => {
    dispatch({ type: "increase", amount: 10 });
  };

  const decrementHandler = () => {
    dispatch({ type: "decrement" });
  };

  const toggleCounterHandler = () => {
    dispatch({ type: "toggle" });
  };

  return (
    <>
      {show && <div>{counter}</div>}
      <button onClick={incrementHandler}>Increment</button>
      <button onClick={increaseHandler}>Increase by 10</button>
      <button onClick={decrementHandler}>Decrement</button>
      <button onClick={toggleCounterHandler}>Toggle Counter</button>
    </>
  );
};

export default Counter;

到這邊實作就完成了!實作的程式碼範例在底下連結,明天將會介紹另一種撰寫 Redux 的 library: Redux toolkit。

程式碼範例(codesandbox)

2021/11/23 補充

這裡補充一個管理多個 Reducer 的範例:
程式碼範例


上一篇
Day14-Redux 篇-介紹 Redux
下一篇
Day16-Redux 篇-認識 Redux Toolkit
系列文
用30天更加認識 React.js 這個好朋友32

尚未有邦友留言

立即登入留言