再來會依據之前的todos範例,詳細的介紹actions、reducers、store,今天我們就從actions開始吧!
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是一個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來做組合。
觸發state的方式,dispatch action給store,而store會拿這個action和prev state讓reducer做處理,update state。
這是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 上,但我們還沒有把這些檔案跟原本的範例連結喔!