0
votes

I am using react-router-dom 5.2.0 to switch to a stateless component in my app, but despite the URL changing, the component never renders immediately, unless I click on the page. The routing in general seems to be broken, because even after that interaction, navigating back to "/home" doesn't work. I have read many tutorials on this and triple checked many things, ensuring I am using "exact" keywords in "Route" and have the most specific routes ordered first, so I don't get why this just won't work.

main.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
import Navbar from './components/Navbar.js';
import styles from './less/index.less'
import { BrowserRouter as Router } from 'react-router-dom';

ReactDOM.render(<Router><App />
    </Router>, document.getElementById('app'));

app.js

import React, { Component } from 'react';
import Navbar from './components/Navbar';
import Home from './components/Home';
import Stuff from './components/Stuff';
import { Route, Switch, withRouter } from 'react-router-dom';



class App extends Component{
   render(){
      return(

         <div class="intro">
            <Navbar />
            <h1>Hello World</h1>
            <Switch>
               <Route exact path="/stuff" component={Stuff} />
               <Route exact path="/" component={Home} />
            </Switch>
         </div>
      );
   }
}

export default App;

Navbar.js

import React, { Component } from 'react';
import styles from '../less/Navbar.less'
import { Link } from 'react-router-dom';

class Navbar extends Component{
   render(){
      return(
         <div class="navbar">
          <div><Link to="/">Home</Link></div>
          <div><Link to="/things">Things</Link></div>
          
              <div class="dropdown">
                <button class="dropbtn">Writing
                  <i class=""></i>
                </button>
                <div class="dropdown-content">
                        <ul>
                            <Link to="/stuff">Stuff</Link>
                            <Link to="/">Stuff2</Link>
                            <Link to="/">Stuff3</Link>
                        </ul>
                    
                </div>
              </div>
        
        </div>
      );
   }
}

export default Navbar;

Stuff.js

import React, { Component } from 'react';

export default class Stuff extends Component{
   render(){
      return(
         <div>
            STUFF COMPONENT
        </div>
      );
   }
}

I made the "Home" component just to have a default, and it just returns a "HOME COMPONENT" like "Stuff" does.

So why is this not working? Do I need to do a state change or use "componentDidMount" inside "Stuff" to really make it render? Or is it an issue with my packages?

Edit: Here is my package.json. Do "react-dom", "react-router-dom", and "react-router" conflict with each other or something?

{
  "name": "Apollo_Website",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack-dev-server --mode development --open --hot",
    "build": "webpack --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@babel/runtime": "^7.12.5",
    "@types/webpack-env": "^1.16.0",
    "@webpack-cli/info": "^1.1.0",
    "@webpack-cli/init": "^1.0.3",
    "@webpack-cli/serve": "^1.1.0",
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.4",
    "babel-node": "0.0.1-security",
    "babel-plugin-require-context-hook": "^1.0.0",
    "babel-plugin-require-context-hook-babel7": "^1.0.0",
    "babel-preset-env": "^1.7.0",
    "babel-preset-react": "^6.24.1",
    "babel-register": "^6.26.0",
    "core-js": "^3.7.0",
    "css": "^3.0.0",
    "css-loader": "^5.0.1",
    "file-loader": "^6.2.0",
    "history": "^5.0.0",
    "html-webpack-plugin": "^4.5.0",
    "image-webpack-loader": "^7.0.1",
    "imagemin": "^7.0.1",
    "imagemin-gifsicle": "^7.0.0",
    "imagemin-mozjpeg": "^9.0.0",
    "imagemin-optipng": "^8.0.0",
    "imagemin-pngquant": "^9.0.1",
    "imagemin-svgo": "^8.0.0",
    "imagemin-webp": "^6.0.0",
    "loose-envify": "^1.4.0",
    "mime-types": "^2.1.27",
    "npm": "^6.14.9",
    "object-assign": "^4.1.1",
    "prop-types": "^15.7.2",
    "punycode": "^2.1.1",
    "querystring": "^0.2.0",
    "react": "^16.14.0",
    "react-dom": "^16.14.0",
    "react-router": "^5.2.0",
    "recursive-readdir": "^2.2.2",
    "schema-utils": "^3.0.0",
    "tiny-invariant": "^1.1.0",
    "tiny-warning": "^1.0.3",
    "url": "^0.11.0",
    "url-loader": "^4.1.1",
    "webpack": "^4.44.2",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.0",
    "webpack-merge": "^5.3.0",
    "yarn": "^1.22.10"
  },
  "devDependencies": {
    "babel-runtime": "^6.26.0",
    "bootstrap": "^4.5.3",
    "chalk": "^2.4.2",
    "cross-spawn": "^6.0.5",
    "findup-sync": "^3.0.0",
    "global-modules": "^2.0.0",
    "home-or-tmp": "^3.0.0",
    "img-loader": "^3.0.2",
    "import-local": "^2.0.0",
    "interpret": "^1.4.0",
    "less": "^3.12.2",
    "less-loader": "^7.0.2",
    "loader-utils": "^1.4.0",
    "lodash": "^4.17.20",
    "mkdirp": "^1.0.4",
    "react-router-dom": "^5.2.0",
    "resolve-url-loader": "^3.1.2",
    "source-map-support": "^0.5.19",
    "style-loader": "^2.0.0",
    "supports-color": "^6.1.0",
    "v8-compile-cache": "^2.2.0",
    "yargs": "^13.3.2"
  },
  "description": ""
}
3

3 Answers

0
votes

Not sure exactly what the issue is. I took your code and created a working example with minimal modifications. It is possible you have a bad version of some dependencies, or perhaps there is more code you could share? Take a look at the example and compare your project to that:

import React, { Component } from "react";
import { BrowserRouter, Link, Route, Switch } from "react-router-dom";

class Home extends Component {
  render() {
    return <div>HOME COMPONENT</div>;
  }
}

class Stuff extends Component {
  render() {
    return <div>STUFF COMPONENT</div>;
  }
}

class MyApp extends Component {
  render() {
    return (
      <div>
        <Navbar />
        <h1>Hello World</h1>
        <Switch>
          <Route exact path="/stuff" component={Stuff} />
          <Route exact path="/" component={Home} />
        </Switch>
      </div>
    );
  }
}

class Navbar extends Component {
  render() {
    return (
      <div class="navbar">
        <div>
          <Link to="/">Home</Link>
        </div>
        <div>
          <Link to="/stuff">Stuff</Link>
        </div>

        <div class="dropdown">
          <button class="dropbtn">
            Writing
            <i class=""></i>
          </button>
          <div class="dropdown-content">
            <ul>
              <Link to="/stuff">Stuff</Link>
              <Link to="/">Stuff2</Link>
              <Link to="/">Stuff3</Link>
            </ul>
          </div>
        </div>
      </div>
    );
  }
}

export default function App() {
  return (
    <BrowserRouter>
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
      </div>
      <MyApp />
    </BrowserRouter>
  );
}
0
votes

Try using this

   <Switch>
       <Route exact path="/stuff"><Stuff/></Route>
       <Route exact path="/"><Home/></Route>
    </Switch>
0
votes

Thanks to jack.benson's comment, I saw my dependencies were the problem. I had "react-router-dom" and its relatives in "devDepencies". I moved it all to "dependencies", and it works perfectly. I'll re-educate myself on dependencies vs. devDependencies to avoid this again. Thanks jack!