6

New to React; I have written a simple page using react-router which on click of the Link should render the corresponding component, but even though the click changes the URL the components are not getting rendered. The home route is displayed irrespective of the Link clicked. Any suggestions on what I might be doing wrong here?

Here is my App.js

import { BrowserRouter as Router, Link, Switch, Route } from "react-router-dom";
import ReactDOM from "react-dom";

const Menu = () => {
  const padding = {
    paddingRight: 5,
  };

  return (
    <div>
      <Link style={padding} to="/">
        anecdotes
      </Link>
      <Link style={padding} to="/create">
        create new
      </Link>
      <Link style={padding} to="/about">
        about
      </Link>
    </div>
  );
};

const AnecdoteList = ({ anecdotes }) => (
  <div>
    <h2>Anecdotes</h2>
    <ul>
      {anecdotes.map((anecdote) => (
        <li key={anecdote.id}>{anecdote.content}</li>
      ))}
    </ul>
  </div>
);

const About = () => (
  <div>
    <h2>About anecdote app</h2>
    <p>According to Wikipedia:</p>

    <em>
      An anecdote is a brief, revealing account of an individual person or an
      incident. Occasionally humorous, anecdotes differ from jokes because their
      primary purpose is not simply to provoke laughter but to reveal a truth
      more general than the brief tale itself, such as to characterize a person
      by delineating a specific quirk or trait, to communicate an abstract idea
      about a person, place, or thing through the concrete details of a short
      narrative. An anecdote is "a story with a point."
    </em>

    <p>
      Software engineering is full of excellent anecdotes, at this app you can
      find the best and add more.
    </p>
  </div>
);

const Footer = () => (
  <div>
    Anecdote app for{" "}
    <a href="https://courses.helsinki.fi/fi/tkt21009">
      Full Stack -websovelluskehitys
    </a>
    . See{" "}
    <a href="https://github.com/fullstack-hy2020/routed-anecdotes/blob/master/src/App.js">
      https://github.com/fullstack-hy2019/routed-anecdotes/blob/master/src/App.js
    </a>{" "}
    for the source code.
  </div>
);

const CreateNew = (props) => {
  const [content, setContent] = useState("");
  const [author, setAuthor] = useState("");
  const [info, setInfo] = useState("");

  const handleSubmit = (e) => {
    e.preventDefault();
    props.addNew({
      content,
      author,
      info,
      votes: 0,
    });
  };

  return (
    <div>
      <h2>create a new anecdote</h2>
      <form onSubmit={handleSubmit}>
        <div>
          content
          <input
            name="content"
            value={content}
            onChange={(e) => setContent(e.target.value)}
          />
        </div>
        <div>
          author
          <input
            name="author"
            value={author}
            onChange={(e) => setAuthor(e.target.value)}
          />
        </div>
        <div>
          url for more info
          <input
            name="info"
            value={info}
            onChange={(e) => setInfo(e.target.value)}
          />
        </div>
        <button>create</button>
      </form>
    </div>
  );
};

const App = () => {
  const [anecdotes, setAnecdotes] = useState([
    {
      content: "If it hurts, do it more often",
      author: "Jez Humble",
      info: "https://martinfowler.com/bliki/FrequencyReducesDifficulty.html",
      votes: 0,
      id: "1",
    },
    {
      content: "Premature optimization is the root of all evil",
      author: "Donald Knuth",
      info: "http://wiki.c2.com/?PrematureOptimization",
      votes: 0,
      id: "2",
    },
  ]);

  const [notification, setNotification] = useState("");

  const addNew = (anecdote) => {
    anecdote.id = (Math.random() * 10000).toFixed(0);
    setAnecdotes(anecdotes.concat(anecdote));
  };

  const anecdoteById = (id) => anecdotes.find((a) => a.id === id);

  const vote = (id) => {
    const anecdote = anecdoteById(id);

    const voted = {
      ...anecdote,
      votes: anecdote.votes + 1,
    };

    setAnecdotes(anecdotes.map((a) => (a.id === id ? voted : a)));
  };

  return (
    <div>
      <h1>Software anecdotes</h1>
      <Router>
        <Menu />
        <Switch>
          <Route path="/">
            <AnecdoteList anecdotes={anecdotes} />
          </Route>
          <Route path="/about">
            <About />
          </Route>
          <Route path="/create">
            <CreateNew addNew={addNew} />
          </Route>
        </Switch>
      </Router>
      <Footer />
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));

Link to the CodeSandBox: https://codesandbox.io/s/fancy-glitter-2ri6k?file=/src/App.js:0-4355

Thanks in advance for your time!

ishon19
  • 177
  • 1
  • 8
  • 1
    You need to use the `exact` prop for your routes, otherwise the first matching one is rendered (in this case the root path). Have a look at the answer here: https://stackoverflow.com/questions/49162311/react-difference-between-route-exact-path-and-route-path – Jayce444 Dec 21 '20 at 05:51
  • That worked indeed.. thanks! – ishon19 Dec 21 '20 at 05:54
  • Although as per the example in the official doc they haven't used the exact prop: https://reactrouter.com/web/guides/quick-start can this be achieved in my case as well? – ishon19 Dec 21 '20 at 06:03
  • 1
    yes you could achieve this by doing what they do in the example and putting the root route last, after the other 2. Though in general relying on the ordering of which you render them rather than the actual route could lead to bugs, and can get complicated as you add more and more routes – Jayce444 Dec 21 '20 at 06:04
  • 1
    Got it! Messed up the ordering.. thanks a lot :) – ishon19 Dec 21 '20 at 06:07

0 Answers0