React-Redux connect失效:类组件无法接收Store props求助
React-Redux connect无法传递Props问题修复(类组件版)
核心问题分析
- Store状态命名空间错误:你的Store配置中将根Reducer挂载到了
todos键下,导致Redux的state结构为{ todos: { dishes, comments, promotions, leaders } },但mapStateToProps直接从state.dishes取值,自然无法获取到数据。 - 拼写错误:
mapStateToProps里的commets是comments的拼写错误,会导致this.props.comments未定义。 - 路由参数获取方式:内部函数组件
DishWithId使用了useParams,虽然可以正常工作,但如果要完全遵循类组件风格,可调整参数传递方式。
修复步骤
1. 修正Store配置
将Reducer直接作为根reducer,去掉todos命名空间,让state结构与你的initialState一致:
// Store配置代码修改后 import {configureStore} from '@reduxjs/toolkit'; import { Reducer, initialState } from './reducer'; export const Store = configureStore({ reducer: Reducer, // 直接使用Reducer作为根reducer initialState: initialState });
2. 修正mapStateToProps的拼写错误
把commets改为comments:
const mapStateToProps = state => { return { dishes: state.dishes, comments: state.comments, // 修正拼写 promotions: state.promotions, leaders : state.leaders } }
3. 优化路由参数传递(可选,保持类组件风格)
将DishWithId改为接收dishes和comments作为props,避免在内部重复connect:
// Main组件中修改DishWithId定义 const DishWithId = ({ dishes, comments }) => { const { dishId } = useParams(); return( <DishDetail dish={dishes.find(dish => dish.id === parseInt(dishId, 10))} comments={comments.filter(comment => comment.dishId === parseInt(dishId, 10))} /> ); } // 对应Route修改为: <Route path="/menu/:dishId" element={<DishWithId dishes={this.props.dishes} comments={this.props.comments} />} />
注:如果完全不想使用hooks,可自行封装
withParams高阶组件来为类组件传递路由参数,示例如下:import { useParams } from 'react-router-dom'; const withParams = (Component) => (props) => { const params = useParams(); return <Component {...props} params={params} />; }; // 定义类组件版DishWithId class DishWithId extends Component { render() { const { dishId } = this.props.params; return ( <DishDetail dish={this.props.dishes.find(dish => dish.id === parseInt(dishId, 10))} comments={this.props.comments.filter(comment => comment.dishId === parseInt(dishId, 10))} /> ); } } // 在Main组件中使用包装后的组件 const ConnectedDishWithId = withParams(DishWithId); // Route改为: <Route path="/menu/:dishId" element={<ConnectedDishWithId dishes={this.props.dishes} comments={this.props.comments} />} />
完整修改后的Main组件代码
import React, { Component } from 'react'; import Home from './HomeComponent'; import Menu from './MenuComponent'; import DishDetail from './DishDetailComponent'; import About from './AboutComponent'; import Contact from './ContactComponent'; import Header from './HeaderComponent'; import Footer from './FooterComponent'; import {Routes, Route, Navigate, useParams} from 'react-router-dom'; import {connect} from 'react-redux'; const mapStateToProps = state => { return { dishes: state.dishes, comments: state.comments, promotions: state.promotions, leaders : state.leaders } } class Main extends Component{ render(){ console.log("this is props xd "+ JSON.stringify(this.props)) const HomePage = () => { return( <Home dish={this.props.dishes.find(dish => dish.featured)} promotions={this.props.promotions.find(promotion => promotion.featured)} leader={this.props.leaders.find(leader => leader.featured)} /> ); }; const DishWithId = ({ dishes, comments }) => { const { dishId } = useParams(); return( <DishDetail dish={dishes.find(dish => dish.id === parseInt(dishId, 10))} comments={comments.filter(comment => comment.dishId === parseInt(dishId, 10))} /> ); } return ( <div > <Header /> <Routes> <Route path="/home" element={<HomePage />} /> <Route exact path="/menu" element={<Menu dishes={this.props.dishes}/>} /> <Route path="/menu/:dishId" element={<DishWithId dishes={this.props.dishes} comments={this.props.comments} />} /> <Route exact path="/contactus" element={<Contact />}/> <Route exact path="/aboutus" element={<About leaders={this.props.leaders}/>}/> <Route path="/*" element={<Navigate replace to="/home" />}/> </Routes> <Footer/> </div> ); } } export default connect(mapStateToProps)(Main);
额外注意事项
- 确保你的应用根组件已经用
Provider包裹了Store,比如在index.js中:import { Provider } from 'react-redux'; import { Store } from './redux/Store'; import { BrowserRouter } from 'react-router-dom'; ReactDOM.createRoot(document.getElementById('root')).render( <Provider store={Store}> <BrowserRouter> <Main /> </BrowserRouter> </Provider> ); - 使用
find替代filter(...)[0],代码更简洁高效。
内容的提问来源于stack exchange,提问作者Cristian Robles
相关产品推荐
相关产品推荐

