我在玩useReducer
react的api,想知道理论(文档)部分和我实现的部分之间的区别。
与useReducer钩子对应的intialState:
const [fields, dispatch] = React.useReducer(formReducer, {
firstName: { value: '', isValid: false },
lastName: { value: '', isValid: false },
});
理论变体
const formActionTypes = {
firstName: 'FIRST_NAME',
lastName: 'LAST_NAME',
};
....
function formReducer(state, action) {
switch (action.type) {
case formActionTypes.firstName:
return { ...state, firstName: { ...action.payload } };
case formActionTypes.lastName:
return { ...state, lastName: { ...action.payload } };
default:
return state;
}
}
....
dispatch({
type: formActionTypes[name], //name is input name
payload: { value, isValid } //value is e.target.value
});
我的暗示
function formReducer(state, action) {
return { ...state, [action.name]: { ...action.payload } };
}
....
dispatch({
name, //name is input name
payload: { value, isValid } //value is e.target.value
});
最佳答案
如果您要的是您所展示的两种减速器,它们都可以工作并产生相同的结果。我认为您从文档中获得的理论版本旨在说明一个特定的概念,尽管您的减速器可能违反了这个概念(尽管这没什么大不了;我们的工作是编写工作代码,而不通过某些纯度测试) !)。
具体来说,您通常希望将动作与状态分离。该动作不仅应该是状态数据结构的镜像;如果您想要这种耦合,则不妨改用useState
并直接设置状态。简化器的意思是通过对动作的描述进行建模来将其解耦,然后只有减速器决定该动作如何作用于状态。例如,您可能决定添加一个透明表单按钮。使用当前的模式,您将必须分派两个动作,这将导致两个状态更新,因为您的动作会对状态进行紧密建模。使用switch语句模式,您可以根据不同类型的操作轻松地应用不同类型的逻辑。
没有错误的答案,只是各有千秋的不同方法。我认为这是通过让reducer逻辑了解字段是否有效来引入更好的去耦的方法:
const SET_FIRST_NAME = Symbol();
const SET_LAST_NAME = Symbol();
const CLEAR_FORM = Symbol();
// Call action creators instead, like: dispatch(setFirstName(e.target.value));
const setFirstName = name => { type: SET_FIRST_NAME, value: name };
const setLastName = name => { type: SET_LAST_NAME, value: name };
const clearForm = () => { type: CLEAR_FORM };
const initialState = {
firstName: { value: '', isValid: false },
lastName: { value: '', isValid: false }
};
const notEmpty = value => !!(value && value.trim().length);
const validateFirstName = notEmpty; // Or replace with different logic
const validateLastName = notEmpty;
const reducer = (state, action) => {
switch (action.type) {
case SET_FIRST_NAME:
return {
...state,
firstName: {
value: action.value,
isValid: validateFirstName(value)
}
}
case SET_LAST_NAME:
return {
...state,
lastName: {
value: action.value,
isValid: validateLastName(value)
}
}
case CLEAR_FORM:
return initialState;
default:
return state;
}
};