htamayo
htamayo

Reputation: 353

Error triggering a Link hook using react-router-v6

I'm updating a sourcecode from react-router-5 to version 6. So far I'm getting this error:

Error: [div] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>

The bug is triggered when I activate a link in this component(QuoteItem.js):

const QuoteItem = (props) => { 
  return (
    <li className={classes.item}>
      <figure>
        <blockquote>
          <p>{props.text}</p>
        </blockquote>
        <figcaption>{props.author}</figcaption>
      </figure>
      <div className={classes.item}>
          <Link className='btn' to={`/quotes/${props.id}`}>View Fullscreen</Link>
        </div>
    </li>
  );
};

in another component (VerQuotes) I defined the routes:

const VerQuotes = () => {
  return (
    <div>
      <main>
        <Layout>
          <Routes>
            <Route path="quotes" element={<AllQuotes />} />

            <Route path="new-quote" element={<NewQuote />} />

            <Route path="quotes/:quoteId" element={<QuoteDetail />} />
          </Routes>
        </Layout>
      </main>
    </div>
  );
};

I'm kind of lost how to tackle the error, your comments will be highly appreciated.

Thanks a lot

Update

QuoteDetail

const QuoteDetail = () => {
  const match = useNavigate();
  const params = useParams();
  const { quoteId } = params;


  const { sendRequest, status, data: loadedQuote, error } = useHttp(getSingleQuote, true);

  //const quote = DUMMY_NOTES.find((quote) => quote.id === params.quoteId);
  useEffect(() => {
    sendRequest(quoteId);
  }, [sendRequest, quoteId]);

  if(status === "pending"){
    return (
      <div className="centered">
        <LoadingSpinner />
      </div>
    );
  }

  if(error){
    return <p className="centered">{error}</p>;
  }

  if (!loadedQuote.text) {
    return <p>No Quote Found!</p>;
  }
  return (
    <Fragment>
      <HighlightedQuote text={loadedQuote.text} author={loadedQuote.author} />
      <Routes>
      <Route path={match}>
        <div className="centered">
          <Link
            className="btn--flat"
            to={`${match}/comments`}
          >
            Load Comments
          </Link>
        </div>
      </Route>
      <Route path={`${match}/comments`} element={<Comments />}></Route>
      </Routes>
    </Fragment>
  );
};

Upvotes: 1

Views: 748

Answers (1)

Drew Reese
Drew Reese

Reputation: 202605

Issues

After tracing your code I found you had a couple issues in QuoteDetail component.

  1. You used const match = useNavigate(); (so match is really the navigate function) but then later used match to attempt to form a path string for a Route.
  2. The Route component's children prop is only for rendering nested routes. The error you see is the use of the div element that isn't a Route component.

Code

<Routes>
  <Route path={match}>
    <div className="centered">
      <Link
        className="btn--flat"
        to={`${match}/comments`}
      >
        Load Comments
      </Link>
    </div>
  </Route>
  <Route path={`${match}/comments`} element={<Comments />}></Route>
</Routes>

Solution

Remove const match = useNavigate(); since it is not used, and place the div into the element prop of the Route. Change the path props to use relative routing from the current route path that's already been built up.

const QuoteDetail = () => {
  const params = useParams();
  const { quoteId } = params;

  const { sendRequest, status, data: loadedQuote, error } = useHttp(
    getSingleQuote,
    true
  );

  //const quote = DUMMY_NOTES.find((quote) => quote.id === params.quoteId);
  useEffect(() => {
    sendRequest(quoteId);
  }, [sendRequest, quoteId]);

  if (status === "pending") {
    return (
      <div className="centered">
        <LoadingSpinner />
      </div>
    );
  }

  if (error) {
    return <p className="centered">{error}</p>;
  }

  if (!loadedQuote.text) {
    return <p>No Quote Found!</p>;
  }
  return (
    <Fragment>
      <HighlightedQuote text={loadedQuote.text} author={loadedQuote.author} />
      <Routes>
        <Route
          path="/"
          element={
            <div className="centered">
              <Link className="btn--flat" to="comments">
                Load Comments
              </Link>
            </div>
          }
        />
        <Route path="comments" element={<Comments />} />
      </Routes>
    </Fragment>
  );
};

Edit error-triggering-a-link-hook-using-react-router-v6

Upvotes: 1

Related Questions