TypeScript React中用useReducer实现点击按钮递增指定属性值
解决React useReducer属性递增的类型错误与渲染问题
问题1:({[key]: value + 1})中value类型unknown
这是因为TypeScript无法推断动态key对应的state值类型,你需要先约束key的合法范围,确保它只能是你定义的属性名。
首先定义属性类型和状态类型:
// 限定合法的属性键 type AttributeKey = 'STR' | 'AGI' | 'INT' | 'CHA'; // 状态类型:每个属性对应一个数值 type AttributesState = Record<AttributeKey, number>;
然后在reducer里,给action的key加上类型约束,这样TypeScript就能确定state[action.key]是number类型:
type Action = { type: 'inc_Attributes'; key: AttributeKey; // 明确key的类型 }; const attributesReducer = (state: AttributesState, action: Action): AttributesState => { switch (action.type) { case 'inc_Attributes': // 这里state[action.key]的类型会被正确推断为number,不会再提示unknown return { ...state, [action.key]: state[action.key] + 1 }; default: return state; } };
问题2:“Objects are not valid as a React child”错误
这个错误几乎都是因为你在JSX里直接渲染了对象而非原始值(字符串、数字等)。检查你的渲染代码:
- 不要直接写
{state},这会把整个状态对象当成React子元素,应该渲染具体属性值,比如{state.STR}。 - 确保按钮点击时传递的dispatch参数正确,不要把对象误传给子组件或渲染逻辑。
举个正确的渲染示例:
export default function Attributes() { const initialState: AttributesState = { STR: 10, AGI: 10, INT: 10, CHA: 10 }; const [state, dispatch] = useReducer(attributesReducer, initialState); const handleIncrement = (key: AttributeKey) => { dispatch({ type: 'inc_Attributes', key }); }; return ( <div> {Object.entries(state).map(([key, value]) => ( <div key={key}> {/* 渲染具体的属性名和数值,而非整个对象 */} <span>{key}: {value}</span> {/* 点击时传递正确的属性键 */} <button onClick={() => handleIncrement(key as AttributeKey)}>+</button> </div> ))} </div> ); }
关键注意点
- 始终给动态key做类型约束,避免TypeScript类型推断失效。
- JSX中只能渲染React允许的子元素类型(字符串、数字、React元素等),绝对不能直接渲染对象或数组(除非你先处理成可渲染的内容)。
内容的提问来源于stack exchange,提问作者bascott
相关产品推荐
相关产品推荐

