0

When I click on "go to cart" my URL changes but there is no change on visual.. When I refresh browser page, it appears. I have tried adding exact many times but it doesn't help. I share my code below. Found few solutions but none of them fixed it.

here is my package.json

{
  "name": "northwind-redux",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.4",
    "@testing-library/react": "^13.1.1",
    "@testing-library/user-event": "^13.5.0",
    "alertifyjs": "^1.13.1",
    "bootstrap": "^5.1.3",
    "react": "^18.0.0",
    "react-bootstrap-validation": "^0.1.11",
    "react-dom": "^18.0.0",
    "react-redux": "^7.2.8",
    "react-router-dom": "^5.3.0",
    "react-scripts": "5.0.1",
    "reactstrap": "^9.0.2",
    "redux": "^4.1.2",
    "redux-thunk": "^2.4.1",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

the application layer is app.js

import React from "react";
import Navi from "../navi/navi";
import { Container } from "reactstrap";
import Dashboard from "./Dashboard";
import { Route, Switch } from "react-router-dom";
import CartDetail from "../cart/CartDetail"
import AddOrUpdateProduct from "../products/AddOrUpdateProduct";

function App() {
  return (
    <Container>
      <Navi></Navi>
        <Switch>
        <Route exact path="/" component={Dashboard} />
        <Route path="/product"  component={Dashboard} />
        <Route exact path="/cart"  component={CartDetail} />
        <Route path="/saveproduct/:productId"  component={AddOrUpdateProduct}/>
       </Switch>      
    </Container>
  );
}

export default App;
    

lastly called CartSummary.js;

import React, { Component } from "react";
import { NavDropdown, Nav, Badge } from "react-bootstrap";
import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import * as cartActions from "../../redux/actions/cartActions";
import { Link } from "react-router-dom";
import alertify from "alertifyjs"; 


class CartSummary extends Component {
  removeFromCart(product) {
    this.props.actions.removeFromCart(product);
    alertify.error(product.productName + " removed from cart");
  }

  renderEmpty() {
    return <Nav.Link>Empty Cart</Nav.Link>;
  }
  renderSummary() {
    return (
      <NavDropdown title="Your cart" id="basic-nav-dropdown">
        {this.props.cart.map((cartItem) => (
          <NavDropdown.Item key={cartItem.product.id}>
            {cartItem.product.productName}{" "}
            <Badge bg="success">{cartItem.quantity}</Badge>{" "}
            <Badge
              bg="danger"
              onClick={() =>
                this.removeFromCart(cartItem.product)
              }
            >
              X
            </Badge>
          </NavDropdown.Item>
        ))}
        <NavDropdown.Item></NavDropdown.Item>
        <NavDropdown.Item href="#action/3.3">Something</NavDropdown.Item>
        <NavDropdown.Divider />
        <Link to="/">Main page</Link>
        <NavDropdown.Divider />
        <Link to="/cart">Go to cart</Link>
      </NavDropdown>
      
    );
  }
  render() {
    return (
      <div>
        {this.props.cart.length > 0 ? this.renderSummary() : this.renderEmpty()}{" "}
      </div>
    );
  }
}

function mapStateToProps(state) {
  return {
    cart: state.cartReducer,
  };
}

function mapDispatchToProps(dispatch) {
  return {
    actions: {
      removeFromCart: bindActionCreators(cartActions.removeFromCart, dispatch),
    },
  };
}
export default connect(mapStateToProps, mapDispatchToProps)(CartSummary);

in App.js coloring of code looks like Dashboard is called correctly (it indicates green color) but the CartSummary color is different (light blue) it also show there is something wrong with it.

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
jengeese
  • 1
  • 2

1 Answers1

0

Since you are using react-router v6, you cannot do what you are trying to do with the old Redux APIs. You are trying to read the router props that react-router till v5 passed to your Components through props to change the redux selectors, but unfortunately the new react-router v6 does not do that anymore, and you have to retrieve the route info through react hooks. This means that you can't access the route params inside the mapStateToProps unless you directly pass the params as a prop.

If you can't upgrade your codebase to using react hooks and redux-toolkit selectors, you have just two options, or you stick with react-router v5, or you should wrap your App Component with an HOC that gives you the params you need:

// HOC withMatch.js

import { useMatch } from 'react-router-dom';

const withMatch = Component => props => {
  const match = useMatch("/*");
  return <Component {...props} match={match} />;
};



// App.js

function App({match}) {
  return (
    <Container>
    <Navi></Navi>
    <Routes>
      <Route path="/" element={<Dashboard/>} />
      <Route path="/product" element={<Dashboard/>}/>
      <Route path="/saveproduct/:productId" element={<AddOrUpdateProduct match={match}/>}/>
      <Route path="/cart" element={<CartDetail/>}/>
     </Routes>
    </Container>
  );
}

export default withMatch(App)

This way your main parent has access to the params and can pass them down as props, hence they can be accessed by react-redux old APIs.

Cesare Polonara
  • 3,473
  • 1
  • 9
  • 19
  • Thank you and what about this: function mapStateToProps(state, ownProps) { const productId = ownProps.match.params.productId; const product = productId && state.productListReducer.length > 0 ? getProductById(state.productListReducer, productId) : {}; return { product, products: state.productListReducer, categories: state.categoryListReducer, }; } const mapDispatchToProps = { getCategories, saveProduct, }; export default connect(mapStateToProps, mapDispatchToProps)(AddOrUpdateProduct); – jengeese Apr 22 '22 at 07:30
  • should I change the code above? – jengeese Apr 22 '22 at 07:31
  • If you add the HOC no, it would work just fine since `ownProps.match` now is not undefined. – Cesare Polonara Apr 22 '22 at 08:14
  • I stucked.. after spending a lot of time in a trial I dont want to waste it. couls you please help me via Github? here is my project link: https://github.com/jengeese/northwind-redux-category-products – jengeese Apr 22 '22 at 19:21
  • Where did this project come from? Did you follow an old udemy course ? This is code from 5-6 years ago, you are even using `bindActionCreators()` in mapDispatchToProps, which was used in early times, and substituted by short object declaration. Unfortunately SO is not a portal to look for collaborations, but to build a global available repository of questions and answers. Since you are using very outdated code style, I suggest you to downgrade react-router to v5, this way you don't need to make any changes, just change `Routes` to `Switch` and render prop from `element` to `component` . – Cesare Polonara Apr 22 '22 at 19:37
  • exactly I am following an old Udemy course. I did what you suggested. Now I got only the rendering problem. everything is fine but only my routes CartDetail and AddOrUpdateProduct dont work. when I click on them, URL changed but nothing as display. When I refresh the page manually, it renders. I found 4-5 questions about this and most of them says it was about "exact path" issue. But it is not. Can you also help me with this? – jengeese Apr 23 '22 at 20:40
  • Update the actual code in your question. – Cesare Polonara Apr 23 '22 at 21:15
  • Code seems right, what do you mean with "green color and light blue" ? What happens whan you click on "Go to cart" link ? CartDetail Component doesn't mount ? Any error in console ? – Cesare Polonara Apr 23 '22 at 22:14
  • I got 5 screen captures with explanations but I am not allowed to upload picture yet :( try to answer; green and light blue; my 2 "Dashboard" code on Route in app.js are green and they work properly. but the "CartDetails" and "AddOrUpdateProduct" are in different color like wrong code. also they are not working. But as you said all of them seems right. when I click on "Go to Cart" the URL changes on my address bar but the page not. yes CartDetail doesn't mount until I refresh the URL manually. neither getting an error in browser console nor in VS code console – jengeese Apr 24 '22 at 06:42