React Route не добавляет косую черту с path="/post/:slug"

По какой-то причине, когда я нажимаю на одно из сообщений в разделе коллекции сообщений, чтобы просмотреть информацию об одном отдельном сообщении, мой код не добавляет косую черту / в URL-адрес, например: http://localhost:3000/postyou-just-could-not-have где URL-адрес, который мне нужен, http://localhost:3000/post/you-just-could-not-have.

Есть ли способ добавить / к URL-адресу или выяснить, почему он не генерируется?

App.js с маршрутом <Route path = "/post/:slug" element = {<SinglePost />} /> в вопросе:

import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Home from './components/Home';
import About from './components/About';
import SinglePost from './components/SinglePost';
import Post from './components/Post';
import Project from './components/Project';
import NavBar from './components/NavBar';

function App() {
  return (
    <Router>
      <NavBar />
      <Routes>
        <Route path = "/" element = {<Home />} exact />
        <Route path = "/about" element = {<About />} />
        <Route path = "/post/:slug" element = {<SinglePost />} />
        <Route path = "/post" element = {<Post />} />
        <Route path = "/project" element = {<Project />} />
      </Routes>
    </Router>
  );
}


export default App;

Компонент SinglePost.js пытается создать URL-адрес из значения slug:

import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import sanityClient from '../client';
import BlockContent from '@sanity/block-content-to-react';
import imageUrlBuilder from '@sanity/image-url';

const builder = imageUrlBuilder(sanityClient);
function urlFor(source) {
  return builder.image(source);
}


export default function SinglePage() {
  const [singlePost, setSinglePost] = useState(null);
  const { slug } = useParams();

 
  useEffect(() => {
    sanityClient
      .fetch(
        `*[slug.current == "${slug}"]{
      title,
      _id,
      slug,
      mainImage{
        asset->{
          _id,
          url
        }
      },
      body,
      "name": author->name,
      "authorImage": author->image
    }`
      )
      .then((data) => setSinglePost(data[0]))
      .catch(console.error);
  }, [slug]);

  if (!singlePost) {
    return <div>Loading...</div>;
  }

  return (
    <main className = "bg-gray-200 min-h-screen p-12">
      <article className = "container shadow-lg mx-auto bg-green-100 rounded-lg">
        <header className = "relative">
          <div className = "absolute h-full w-full flex items-center justify-center p-8">
            <div className = "bg-white bg-opacity-75 rounded p-12">
              <h1 className = "cursive text-3xl lg:text-6xl mb-4">
                {singlePost.title}
              </h1>
              <div className = "flex justify-center text-gray-800">
                <img
                  src = {urlFor(singlePost.authorImage).url()}
                  alt = "bob"
                  className = "w-10 h-10 rouded-full"
                />
                <p className = "cursive flex items-center pl-2 text-2xl">
                  {singlePost.name}
                </p>
              </div>
            </div>
          </div>
          <img
            src = {singlePost.mainImage.asset.url}
            alt = "gary"
            className = "w-full object-cover rounded-t"
            style = {{ height: '400px' }}
          />
        </header>
        <div className = "px-16 lg:px-48 py-12 lg:py-20 prose lg:prose-xl max-w-full">
          <BlockContent
            blocks = {singlePost.body}
            projectId = "notReally"
            dataset = "production"
          />
        </div>
      </article>
    </main>
  );
}



Adding Post.js : 





import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import sanityClient from '../client';

export default function Post() {
  const [postData, setPost] = useState(null);


  useEffect(() => {
    sanityClient
      .fetch(
        `*[_type == "post"]{
      title,
      slug,
      mainImage{
        asset->{
          _id,
          url
        },
        alt
      }
    }`
      )
      .then((data) => setPost(data))
      .catch(console.error);
  }, []);

  //anything wrapped in Link makes it clickable
  return (
    <main className = "bg-green-100 min-h-screen p-12">
      <section className = "container mx-auto">
        <h1 className = "text-5xl flex justify-center cursive">Blog Post Page</h1>
        <h2 className = "text-lg text=gray-600 flex justify-center mb-12">
          Welcome Doggies
        </h2>
        <div className = "grid md:grid-cols-2 lg:grid-cols-3 gap-8">
          {postData &&
            postData.map((post, index) => (
              <article>
                <Link to = {'/post' + post.slug.current} key = {post.slug.current}>
                  <span
                    className = "block h-64 relative rounded shadow leading-snug bg-white border-l-8 border-green-400"
                    key = {index}
                  >
                    <img
                      src = {post.mainImage.asset.url}
                      alt = "photo"
                      className = "w-full h-full rounded-r object-cover absolute"
                    />
                    <span className = "block relative h-full flex justify-end items-end pr-4 pb-4">
                      <h3 className = "text-gray-800 text-lg font-blog px-3 py-4 bg-red-700 text-red-100 bg-opacity-75 rounded">
                        {post.title}
                      </h3>
                    </span>
                  </span>
                </Link>
              </article>
            ))}
        </div>
      </section>
    </main>
  );
}

🤔 А знаете ли вы, что...
JavaScript может выполняться как на стороне клиента (в браузере), так и на стороне сервера (с использованием Node.js).


67
1

Ответ:

Решено

Ссылки по умолчанию относятся к иерархии маршрутов, если только не задано значение, начинающееся с /.

Подробнее о ссылке

В <Post /> попробуйте один из следующих способов:

<Link to = {post.slug.current} key = {post.slug.current}>
...
/Link>

Или:

<Link to = {'/post/' + post.slug.current} key = {post.slug.current}>
...
/Link>

Мы надеемся, что они сгенерируют правильный путь как /post/:slug.