Search code examples
reactjsreduxreact-reduxredux-router

Post ID route showing up in other components


I am learning router and redux. I am trying to create a blog. Now the post ID route is showing up in other components like About and portfolio but not in home page because I have made it an exact path.

https://github.com/chiranjeebhub/router-redux

Post.js:

import React, { Component } from "react";
import { connect } from "react-redux";

class Post extends Component {
  render() {
    const post = this.props.post ? (
      <div>
        <h4>{this.props.post.title}</h4>
        <p>{this.props.post.body}</p>
      </div>
    ) : (
      <div>
        <p>loading post ... </p>
      </div>
    );
    return <div>{post}</div>;
  }
}

const mapStateToProps = (state, ownProps) => {
  let id = ownProps.match.params.post_id;
  return {
    post: state.posts.find(post => post.id == id)
  };
};

export default connect(mapStateToProps)(Post);

My Routers:

import React, { Component } from "react";
import { BrowserRouter, Route } from "react-router-dom";
import NavBar from "./Components/NavBar";
import Home from "./Components/Home";
import About from "./Components/About";
import Post from "./Components/post";
import Portfolio from "./Components/portfolio";

class App extends Component {
  render() {
    return (
      <BrowserRouter>
        <div className="App">
          <NavBar />
          <Route exact path="/" component={Home} />
          <Route path="/about" component={About} />
          <Route path="/portfolio" component={Portfolio} />
          <Route path="/:post_id" component={Post} />
        </div>
      </BrowserRouter>
    );
  }
}

export default App;

About.js

import React, { Component } from "react";

class About extends Component {
  render() {
    return (
      <div>
        <h1>About Me</h1>
      </div>
    );
  }
}

export default About;

Reducer

const initState = {
  posts: [
    { id: "1", title: "title1", body: "body1" },
    { id: "2", title: "title2", body: "body2" },
    { id: "3", title: "title3", body: "body3" },
    { id: "4", title: "title4", body: "body4" }
  ]
};

const rootReducer = (state = initState, action) => {
  return state;
};

export default rootReducer;

Now when I load "About" component the "Loading Posts..." shows up from post.js


Solution

  • You are having issue because the path

    <Route path="/:post_id" component={Post} />
    

    shows that a dynamic value is expected at the post_id placeholder. As post_id is just a placeholder using about, portfolio, 1, etc as route parameters will satisfy the condition.

    i.e

    // All of them are valid
    /about
    /portfolio
    /1
    

    So Post component shows up along with other components.

    Therefore you should wrap Route components with Switch Component. As Switch component only renders the first child that matches the path so Post component will not show up when /about and /portfolio is used.

    import { BrowserRouter, Route, Switch } from 'react-router-dom';
    
     <BrowserRouter>
        <div className="App">
          <NavBar />
          <Switch>
            <Route exact path="/" component={Home} />
            <Route path="/about" component={About} />
            <Route path="/portfolio" component={Portfolio} />
            <Route path="/:post_id" component={Post} />
          </Switch>
        </div>
      </BrowserRouter>