iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 19
0
Modern Web

寫React的那些事系列 第 19

React Day19 - Redux Action

再來會依據之前的todos範例,詳細的介紹actions、reducers、store,今天我們就從actions開始吧!

Action


Action是一個plain object,這個object中一定會有一個 type 屬性,用來傳達要改變的類型,通常定義成常數,可以把整個專案的actions常數都整理成一個檔案,這樣比較方便管理,可以知道有哪些類型被定義過,但如果整個專案會用到的很少,也可以只寫在action檔案中。

除了 type 屬性,還可以增加其他會用到的屬性,例如要改變的值,或是陣列的索引,通常建議減少其他屬性的內容,只傳必要的內容,假設要更新todos陣列的資料,只傳要改變的索引值和被改變的內容,甚至某些情況只需要傳遞 type

例如,要改變todos陣列1的task內容:

// 常數記得大寫
const EDIT_TASK = 'EDIT_TASK';

// action
{
  type: EDIT_TASK,
  index: 1,
  task: 'Go to bed early'
}

或是,只是切換task是否完成,就需要傳入todos陣列:

// 常數記得大寫
const TOGGLE_TASK = 'TOGGLE_TASK';

// action
{
  type: TOGGLE_TASK,
  index: 1
}

Action Creator


上面提到action是一個object,而action creator就是return這個object的function,產生要回傳的action,例如:

const ADD_TASK = 'ADD_TASK';

// action creator
function addTask(task) {
  return {
    type: ADD_TASK,
    task
  };
}

有時候一個動作會需要觸發多個action,可以用action creator來做組合。

store.dispatch(action)


觸發state的方式,dispatch action給store,而store會拿這個action和prev state讓reducer做處理,update state。

bindActionCreators(actionCreators, dispatch)


這是Redux提供的一個方法,可以把一個或多個action creator轉換成同樣名稱當作key的object,並且加上dispatch,所以這些action creator就可以直接被呼叫。當我們希望action可以被任何component使用,而不需要一定要加上dispatch的時候,就會使用到。

這邊用簡單的案例說明,資料夾架構如下:

├── actions
│  └── todos.js
└── TodoListContainer.js

todos.js

// action type
export const ADD_TASK = 'ADD_TASK';
export const EDIT_TASK = 'EDIT_TASK';
export const DELETE_TASK = 'DELETE_TASK';
export const TOGGLE_TASK = 'TOGGLE_TASK';

// action creator
export function addTask(task){
  return {
    type: types.ADD_TASK,
    task
  };
}
export function editTask(idx, task){
  return {
    type: types.EDIT_TASK,
    idx,
    task
  };
}
export function deleteTask(idx){
  return {
    type: types.DELETE_TASK,
    idx
  };
}
export function toggleTask(idx){
  return {
    type: types.TOGGLE_TASK,
    idx
  };
}

TodoListContainer.js

import { Component } from 'react';
import { bindActionCreators } from 'redux';
import * as TodosActionCreators from './actions/todos';

class TodoListContainer extends Component {
  render() {
    let todosActionCreators = bindActionCreators(TodosActionCreators, dispatch);
    return (
      <TodoList {...boundActionCreators} />
    );
  }
}

這樣在TodoList收到的props就會是這樣:

{
  addTask: Function,
  editTask: Function,
  deleteTask: Function,
  toggleTask: Function
}

並且可以直接呼叫這些function。

目前先建立了actions在原本的todos專案中,更新的檔案放在Git 上,但我們還沒有把這些檔案跟原本的範例連結喔!


上一篇
React Day18 - Redux 三大原則
下一篇
React Day20 - Redux Reducer
系列文
寫React的那些事31

尚未有邦友留言

立即登入留言