簡單看了下,這個規則要點是:redux
type是必須的,其餘三個可選。規定action不能再有其餘屬性了。bash
不要經過相似GET_DATA_SUCCESS
和GET_DATA_FAIL
這樣的type去處理錯誤。而是經過設置error:true處理app
{
type: 'GET_DATA',
payload: new Error(),
error: true
}
複製代碼
redux-actions是建立各類actionCreater,action只是簡寫。調用生成的actionCreater函數纔會產生真正的action。函數
例如oop
const a = createAction('INCREMENT');
console.log(a(111))
複製代碼
產生的結果是ui
{
type: 'INCREMENT',
payload: 111
}
複製代碼
const actionCreater = createAction('INCREMENT');
複製代碼
const reducer = handleAction(
actionCreator,
(state, action) => ({
...state,
counter: state.counter + 1,
}),
{ counter: 1 }
);
複製代碼
dispatch(actionCreater())
複製代碼
經過以上三步,能夠看出端倪了,可是並沒什麼用,咱們用redux的痛點是什麼?一堆switch,dispatch時候type亂飛等。下面讓咱們用redux-actions來實現經典官方例子todo。spa
actions
code
export const add = createAction('ADD_TODO');
export const del = createAction('DELETE_TODO');
export const toggle = createAction('TOGGLE_TODO');
複製代碼
reducers
對象
const defaultState = [];
const reducer = handleActions({
[add]: (state, {payload}) => {
return [...state, {
text: payload,
done: false
}];
},
[del]: (state, {payload}) => {
const ind = state.findIndex(item => item.text === payload);
return [...state.slice(0, ind), ...state.slice(ind + 1)];
},
[toggle]: (state, {payload}) => {
const ind = state.findIndex(item => item.text === payload);
const todo = state[ind];
console.log(ind, todo)
return [
...state.slice(0, ind),
{
...todo,
done: !todo.done
},
...state.slice(ind + 1)
]
}
}, defaultState)
複製代碼
組件
rem
function App() {
const [todo, setTodo] = useState('');
const dispatch = useDispatch();
const state = useSelector(state => state);
console.log('app');
function handleChange(e) {
setTodo(e.target.value);
}
function handleAdd() {
dispatch(add(todo));
setTodo('');
}
return (
<div className="App">
<input value={todo} onChange={handleChange} />
<button onClick={handleAdd}>Add</button>
<br />
<ul>
{state.map(({ text, done }) => (
<li key={text}>
<span
onClick={() => dispatch(toggle(text))}
style={done ? { textDecoration: 'line-through' } : null}
>
{text}
</span>
<button onClick={() => dispatch(del(text))}>X</button>
</li>
))}
</ul>
</div>
);
}
複製代碼
定義action
const increment = createAction('INCREMENT')
複製代碼
在reducer中引用
const reducer = handleActionsWithImmer({
[increment]: (state) => {
return state + 1;
},
...
複製代碼
在組件中引用
dispatch(increment());
複製代碼
const noop = createAction('NOOP');
const error = new TypeError('not a number');
noop(error);
複製代碼
將自動生成一個error爲true的action
{
type: 'NOOP',
payload: error,
error: true
}
複製代碼
在reducer中,能夠自行判斷error爲true做處理,也能夠以下聲明式處理。這樣,正常action會走next處理,若是error爲true的action會走throw處理
handleAction(noop, {
next(state, action) {
return action.payload;
},
throw(state, action) {
console.log('出錯了', state, action);
return state;
}
}, 'xxxxx');
複製代碼