使用TypeScript开发Redux时无法将State映射到Props的问题求助
解决TypeScript中Redux State映射到Props的问题
我猜你在把JavaScript版的Redux教程转成TypeScript时,卡在了State到Props的映射环节。先把你给出的代码片段补全梳理清楚,再一步步解决这个问题。
先梳理你的现有代码(补全片段)
你提供的App.tsx大概是这样的:
import * as React from 'react'; import Todo from '../models/Todo'; import { createStore } from 'redux'; import { Provider } from 'react-redux'; import Main from './Main'; export interface State { todoList: Todo[]; filterStatus: string; isAdding: boolean; } const defaultState: State = { todoList: [], filterStatus: 'SHOW_ALL', isAdding: false, }; const reducer = (state: State = defaultState, action: any) => { // 你的reducer逻辑应该在这里 switch(action.type) { // 比如添加todo、切换筛选状态等逻辑 default: return state; } }; const store = createStore(reducer); const App = () => { return ( <Provider store={store}> <Main /> </Provider> ); }; export default App;
常见问题及两种解决方式
在TypeScript中用Redux做状态映射,核心问题是类型定义不完整,下面分两种常用场景说明解决方案:
方式1:用useSelector(函数组件推荐)
如果你的Main.tsx是函数组件,用useSelector获取状态时,需要明确指定State的类型,让TypeScript识别状态结构:
// Main.tsx import * as React from 'react'; import { useSelector } from 'react-redux'; import { State } from './App'; // 导入全局State类型 const Main = () => { // 给useSelector指定State类型,精准选取需要的状态 const todoList = useSelector((state: State) => state.todoList); const filterStatus = useSelector((state: State) => state.filterStatus); const isAdding = useSelector((state: State) => state.isAdding); return ( <div> <h2>Todo List</h2> {todoList.map(todo => ( <div key={todo.id}>{todo.text}</div> ))} </div> ); }; export default Main;
方式2:用connect(类组件或传统写法)
如果用connect高阶组件,需要定义MapStateToProps的类型,同时明确组件Props的结构:
// Main.tsx import * as React from 'react'; import { connect, ConnectedProps } from 'react-redux'; import { State } from './App'; import Todo from '../models/Todo'; // 组件自身的Props(如果有的话) interface OwnProps { // 比如自定义的回调、参数等 } // 定义mapStateToProps,明确参数为State类型 const mapStateToProps = (state: State) => ({ todoList: state.todoList, filterStatus: state.filterStatus, isAdding: state.isAdding, }); // 生成连接后的完整Props类型 type Props = OwnProps & ConnectedProps<typeof connector>; const connector = connect(mapStateToProps); const Main = (props: Props) => { const { todoList, filterStatus, isAdding } = props; return ( <div> <h2>Todo List</h2> {todoList.map(todo => ( <div key={todo.id}>{todo.text}</div> ))} </div> ); }; export default connector(Main);
关键注意事项
- 别忽略Action的类型:你现在的reducer里
action用了any,这会丢失TypeScript的类型检查,建议定义Action类型:// 单独定义Action类型,放在types/index.ts里更方便全局引用 type Action = | { type: 'ADD_TODO'; payload: Todo } | { type: 'SET_FILTER'; payload: string } | { type: 'TOGGLE_ADDING' }; const reducer = (state: State = defaultState, action: Action) => { switch(action.type) { case 'ADD_TODO': return { ...state, todoList: [...state.todoList, action.payload] }; // 其他case逻辑 default: return state; } }; - State类型全局化:最好把
State和Action类型单独放在一个文件(比如src/types/index.ts),而不是只在App.tsx里定义,这样其他组件导入更方便。 - 拒绝
any类型:尽量用明确的类型代替any,TypeScript才能帮你提前发现潜在错误。
内容的提问来源于stack exchange,提问作者Twitter khuong291
相关产品推荐
相关产品推荐

