您的帖子清楚地反映出对 React 和 hooks 的工作原理缺乏了解。在遵循互联网上任何令人困惑的指南之前,请阅读official documentation。官方文档不会出错,因为它首先展示了它的用途。
首先,要使您的代码正常工作,您必须将useReducerState 移出组件。为什么?每次渲染组件时,useReducerState 将是一个新函数。你的函数是一个钩子,你最好将它移动到它自己的文件中并导出它。
其次,如果您了解 Redux,请将 useReducer 视为组件的本地存储。 useReducer 的第一个参数是一个reducer,reducer 是一个纯函数,将状态作为第一个参数,action 作为第二个参数并返回一个新的状态。所以,我根本不明白这一行:
const reducer = (prev, next) => ({ ...prev, ...next });
“next”应该是一个动作,它是一个具有两个属性的对象:type(被调度的动作的类型)和payload(嗯,有效载荷) .
这一行更令人困惑:
const [state, setState] = useReducerState({
而useReducer 的签名是这样的:
const [state, dispatch] = useReducer(reducer, initialArg, init);
所以你是怎么得到setState的对我来说是个谜。
最后,我没有在你的组件中看到任何调度(?)为什么要使用 useReducer 呢?从您的代码来看,您似乎想使用useState,它确实在数组中返回了一个 setState。
由于我不太明白发生了什么,我无法将表单重置为默认值,这似乎是 reducer 的重点。
不清楚你在这里的意思,但 reducer 的重点是调度一个动作,该动作将指示你的状态发生什么变化并返回新的状态。使用useReducer,您不必这样做:
setState(prevState => ({
...prevState,
[proPToUpdate]: value
}))
官方文档摘录:
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
在你的情况下,大致如下:
const initialState = {
input1: "",
input2: "",
input 3: "",
input 4: "",
input 6: "",
input 7: "",
input 8: "",
input 9: "",
}
function reducer(state, action) {
switch (action.type) {
case 'setInput1':
return { ...state, input1: action.payload};
case 'setInput2':
return { ...state, input2: action.payload};
case 'reset':
return initialState;
default:
throw new Error();
}
}
...
const [state, dispatch] = useReducer(reducer, initialState)
...
dispatch({ type: 'reset' });
dispatch({ type: 'setInput1', payload: value });
更多。是的,这段代码
const reducer = (prev, next) => ({ ...prev, ...next });
return useReducer(reducer, initialState);
确实有效,但您失去了可读性。让我们直言不讳。使用减速器时,您必须向它传递一个动作。一个动作必须有一个类型。上面的代码有效,但它是错误的。它正在转移useReducer 的合法用途,以获取什么?更少的代码?是的,但绝不会以牺牲可读性和语义为代价。当您打算使用.forEach 时,这与使用.map 而不是.forEach 相同。
如果我在某处看到这个(由其他人写的):
setState({ [proToUpdate]: value });
你觉得我会怎么做?我会说,嘿,你的代码错了,应该是
setState(prevState => ({ ...prevState, [proToUpdate]: value }));
并修复它。不知道有一个 useReducer 在幕后发挥作用......这是错误的。
我见过很多人为了讨价还价几行代码而做一些奇怪的事情,而且这并不总是很漂亮,通常来自互联网上的指南、Medium 等!不要忘记,您可能并不孤单地处理此代码。让它对每个人都可读,更重要的是,使其有意义。