Search code examples
reactjsredux

So I've been trying to get React-Redux connect to work but the component is not recieving any props from the store


I'm been trying to learn React by following some Coursera course and just got to Redux but the React they have been using, and other packages are outdated(Usually deprecated,He also uses v5 of react-router-dom and Redux(createStore)), so I've been trying my best to find the replacements in the new versions. I have tried looking for a way to fix it but most information I find says that it's better to use functional components with hooks, but this course doesn't have anything about hooks.

Below is my main component, the course used withRouter but that was removed.

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, useLocation, useNavigate} from 'react-router-dom';
import {connect} from 'react-redux';

const  mapStateToProps = state =>   {
        return{
            dishes: state.dishes,
            commets: state.comments,
            promotions: state.promotions,
            leaders : state.leaders
        }
}



class Main extends Component{
    constructor(props){
        super(props);

    }

   

    render(){
        console.log("this is props xd "+ JSON.stringify(this.props))
        const HomePage = () => {
            return(
                <Home dish={this.props.dishes.filter((dish)=>dish.featured)[0]} 
                    promotions={this.props.promotions.filter((promotion)=> promotion.featured)[0]}
                    leader={this.props.leaders.filter((leader)=>leader.featured)[0]}
                
                />
            );
        };

        const DishWithId = () =>{
            //in V6 of reach route dom, we need to use useParams() to get parms zz
            const match = useParams();
            return(
                <DishDetail dish={this.props.dishes.filter((dish)=>{
                    if(dish.id=== parseInt(match.dishId, 10)){
                        return true;
                    } 
                    return false;
                })[0]}

                comments={this.props.comments.filter((comment)=> comment.dishId === parseInt(match.dishId, 10))}
                />
            );
        }

        return (
            <div >
                <Header />                
                <Routes>
                    <Route path="/home" element={<HomePage />} />
                    {/* this path should match exactly to the route when using exact */}
                    <Route exact path="/menu" element={<Menu dishes={this.props.dishes}/>} />
                    <Route path="/menu/:dishId" element={<DishWithId />} />
                    <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);

Below is my configureStore and reducer

import {configureStore} from '@reduxjs/toolkit';
import { Reducer, initialState } from './reducer';


export const Store = configureStore({
  reducer:{
    todos: Reducer
    
  },
  initialState: initialState
});

Reducer

import {DISHES} from '../shared/dishes';
import { COMMENTS } from '../shared/comments';
import { LEADERS } from '../shared/leaders';
import { PROMOTIONS } from '../shared/promotions';

export const initialState = {
  dishes: DISHES,
  comments: COMMENTS,
  promotions: PROMOTIONS,
  leaders: LEADERS
};


export const Reducer = (state = initialState, action) =>{
  return state;
}

Solution

  • This is a common issue with the Coursera React course, where all exercises have been designed using older package versions and lots of stuff has been deprecated, replaced or removed altogether (doing that now and experiencing the same pain). The specific issue - find an alternative for the class component export that uses the withRouter method that is removed in v6 and higher. I searched around for a bit and found the solution in a post:

    withRouter is not exported from react-router-dom

    We can get it to work by defining our our own withRouter function and use it the same way the original function was supposed to be used.

    import {Routes, Route, Navigate, useLocation, useNavigate, useParams} from 'react-router-dom'
    import { connect } from 'react-redux'
    
    const mapStateToProps = reduxStoreState => {
      return({
        dishes: reduxStoreState.dishes,
        comments: reduxStoreState.comments,
        leaders: reduxStoreState.leaders,
        promotions: reduxStoreState.promotions
      })
    }
    
    class MainAppManager extends Component {
       ...
    }
    
    const withRouter = Component => {
      const ComponentWithRouterProp = props => {
        let location = useLocation()
        let navigate = useNavigate()
        let params = useParams()
        return (
          <Component {...props} router={{ location, navigate, params }}/>
        )
      }
      return ComponentWithRouterProp
    }
    
    export default withRouter(connect(mapStateToProps)(MainAppManager))