首先,讓我們來給 action 下個定義。
Actions 是把數(shù)據(jù)從應(yīng)用(譯者注:這里之所以不叫 view 是因為這些數(shù)據(jù)有可能是服務(wù)器響應(yīng),用戶輸入或其它非 view 的數(shù)據(jù) )傳到 store 的有效載荷。它是 store 數(shù)據(jù)的惟一來源。用法是通過 store.dispatch()
把 action 傳到 store。
添加新 todo 任務(wù)的 action 是這樣的:
const ADD_TODO = 'ADD_TODO';
{
type: 'ADD_TODO',
text: 'Build my first Redux app'
}
Action 本質(zhì)是 JavaScript 普通對象。我們約定,action 內(nèi)使用一個字符串類型的 type
字段來表示將要執(zhí)行的動作。多數(shù)情況下,type
會被定義成字符串常量。當應(yīng)用規(guī)模越來越大時,建議使用單獨的模塊或文件來存放 action。
import { ADD_TODO, REMOVE_TODO } from '../actionTypes';
樣板文件使用提醒
使用單獨的模塊或文件來定義 action type 常量并不是必須的,甚至根本不需要定義。對于小應(yīng)用來說,使用字符串做 action type 更方便些。不過,在大型應(yīng)用中最多把它們顯式地定義成常量。參照 減少樣板代碼 獲取保持代碼干凈的實踐經(jīng)驗。
除了 type
字段外,action 對象的結(jié)構(gòu)完全取決于你。參照 Flux 標準 Action 獲取如何組織 action 的建議。
這時,我們還需要再添加一個 action type 來標記任務(wù)完成。因為數(shù)據(jù)是存放在數(shù)組中的,我們通過 index
來標識任務(wù)。實際項目中一般會在新建內(nèi)容的時候生成惟一的 ID 做標識。
{
type: COMPLETE_TODO,
index: 5
}
action 中傳遞的數(shù)據(jù)越少越好。比如,這里傳遞 index
就比把整個任務(wù)對象傳過去要好。
最后,再添加一個 action 類型來表示當前展示的任務(wù)狀態(tài)。
{
type: SET_VISIBILITY_FILTER,
filter: SHOW_COMPLETED
}
Action 創(chuàng)建函數(shù) 就是生成 action 的方法?!癮ction” 和 “action 創(chuàng)建函數(shù)” 這兩個概念很容易混在一起,使用時最好注意區(qū)分。
在 傳統(tǒng)的 Flux 實現(xiàn)中,當調(diào)用 action 創(chuàng)建函數(shù)時,一般會觸發(fā)一個 dispatch,像這樣:
function addTodoWithDispatch(text) {
const action = {
type: ADD_TODO,
text
};
dispatch(action);
}
不同的是,Redux 中的 action 創(chuàng)建函數(shù)是 純函數(shù),它沒有任何副作用,只是返回 action 對象而已。
function addTodo(text) {
return {
type: ADD_TODO,
text
};
}
這讓代碼更易于測試和移植。只需把 action 創(chuàng)建函數(shù)的結(jié)果傳給 dispatch()
方法即可實例化 dispatch。
dispatch(addTodo(text));
dispatch(completeTodo(index));
或者創(chuàng)建一個 被綁定的 action 創(chuàng)建函數(shù) 來自動 dispatch:
const boundAddTodo = (text) => dispatch(addTodo(text));
const boundCompleteTodo = (index) => dispatch(CompleteTodo(index));
可以這樣調(diào)用:
boundAddTodo(text);
boundCompleteTodo(index);
store 里能直接通過 store.dispatch()
調(diào)用 dispatch()
方法,但是多數(shù)情況下你會使用 react-redux 提供的 connect()
幫助器來調(diào)用。bindActionCreators()
可以自動把多個 action 創(chuàng)建函數(shù) 綁定到 dispatch()
方法上。
actions.js
/*
* action 類型
*/
export const ADD_TODO = 'ADD_TODO';
export const COMPLETE_TODO = 'COMPLETE_TODO';
export const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER';
/*
* 其它的常量
*/
export const VisibilityFilters = {
SHOW_ALL: 'SHOW_ALL',
SHOW_COMPLETED: 'SHOW_COMPLETED',
SHOW_ACTIVE: 'SHOW_ACTIVE'
};
/*
* action 創(chuàng)建函數(shù)
*/
export function addTodo(text) {
return { type: ADD_TODO, text };
}
export function completeTodo(index) {
return { type: COMPLETE_TODO, index };
}
export function setVisibilityFilter(filter) {
return { type: SET_VISIBILITY_FILTER, filter };
}
現(xiàn)在讓我們 開發(fā)一些 reducers 來指定發(fā)起 action 后 state 應(yīng)該如何更新。
高級用戶建議
如果你已經(jīng)熟悉這些基本概念且已經(jīng)完成了這個示例,不要忘了看一下在 高級教程 中的 異步 actions,你將學(xué)習如何處理 AJAX 響應(yīng)和如何把 action 創(chuàng)建函數(shù)組合成異步控制流。
更多建議: