1
votes

this is my first post in Stackoverflow and I hope you guys can give me some guidance.

I'm currently learning React Router and it seems that I got stucked on an error or bug that I can't find to solve. To give you a little overview about the setup, here it is:

I'm using CRA with React-Router-DOM 5.0.1. I'm using React Hooks to practice and using latest version of React 16.8.6

This is an app that reads a local API and it renders its data on different components. Here is the code:

App.js

import React, { Fragment, useState, useEffect } from 'react';
import { BrowserRouter, Link, Route, Switch } from 'react-router-dom';
import axios from 'axios';

import Writers from './Writers';

function App() {
  const [writers, setWriters] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      const result = await axios('http://localhost:3004/writers');
      setWriters(result.data);
    };

    fetchData();
  }, []);

  return (
    <BrowserRouter>
      <Fragment>
        <ul>
          <li>
            <Link to='/'>Home</Link>
          </li>
          <li>
            <Link to='/writers'>Writers</Link>
          </li>
        </ul>

        <Switch>
          <Route exact path='/' render={() => <div>Home</div>} />
          <Route
            exact
            path='/writers'
            render={props => <Writers {...props} writers={writers} />}
          />
        </Switch>
      </Fragment>
    </BrowserRouter>
  );
}

export default App;

Writers.js

import React, { Fragment } from 'react';
import { Route, Link } from 'react-router-dom';
import Writer from './Writer/index';

const Writers = props => {
  console.log(props);
  return (
    <Fragment>
      <ul>
        {props.writers.map(({ id, name }) => (
          <li key={id}>
            <Link to={`${props.match.url}/${id}`}>{name}</Link>
          </li>
        ))}
      </ul>

      <Route
        path={`${props.match.url}/:writerID`}
        render={props => <Writer {...props} />}
      />
    </Fragment>
  );
};

export default Writers;

Writer.js

import React, { Fragment } from 'react';

const Writer = ({ match, id, name, description }) => {
  console.log(match);
  return <Fragment>id name description</Fragment>;
};

export default Writer;

So I'm having an issue in Writers.js where I'm passing the params "/:writerID", this params doesn't get to Writer component and actually Writer component never gets rendered at all

<Route
        path={`${props.match.url}/:writerID`}
        render={props => <Writer {...props} />}
      />

If I remove :writerID from the path prop, the component Writer gets rendered BUT it doesn't allow me route it the unique path that I'm looking for.

Any idea why this might be happening? Any help will be greatly appreciated.

I have tried making sure I have the correct exports on my files and they are, in fact, I don't see any errors from the CRA logs. Also, I remove the params from the path props and it seems that the Writer components renders but if I put it again, it doesn't work.

App.js passing Writers with props and writers data

<Route
            exact
            path='/writers'
            render={props => <Writers {...props} writers={writers} />}
          />

Writers.js receives the data and Route props so I can access Match props but this component does NOT render Writer component neither get the match.params prop.

<Route
        path={`${props.match.url}/:writerID`}
        render={props => <Writer {...props} />}
      />

Expected behavior: Writer.js should be render when trying to click on any individual writer and it should allow me to get the match.params prop.

Actual Behavior: Writer.js does not gets rendered and if I remove the path prop from Route, it gets render but I can't access the individual id.

1

1 Answers

0
votes

In your Route path for /writers you are using the exact prop, which will lead to any nested Route not being rendered. Remove the exact prop and your Routes will work

<Route
        exact
        path='/writers'
        render={props => <Writers {...props} writers={writers} />}
      />

Also as a thumb rule you should use match.url for Link path and match.path for a Route path