【问题标题】:How to get React Router to recognize a new route on a dynamic path如何让 React Router 识别动态路径上的新路由
【发布时间】:2021-06-30 23:20:00
【问题描述】:

所以我有一个 NavBar 组件,如果我从“/sites/1”到“/categories/1”或从“/sites”到“/categories”甚至“/sites”的任何内容,创建的链接都可以正常工作/1" 到 "/sites" 但是当我在一个类别显示页面上时不起作用/5" 例如。我认为问题与确切路径是动态的事实有关,并且路由器将两条路径视为同一事物,直到硬重新加载。下面是我的代码。有什么方法可以使用 Link 并让该组件重新渲染,还是每次都必须使用锚标记并重新加载?

import React, { useState, useEffect } from "react"
import { Switch, Route, Link, Redirect } from "react-router-dom"

import SitesIndex from "./SitesIndex";
import SiteShow from "./SiteShow";
import AddNewSiteForm from "./AddNewSiteForm"
import CategoryShow from "./CategoryShow"

const NavBar = props => {
  const [categories, setCategories] = useState([])

  const fetchCategories = async() =>{
    try {
      const response = await fetch("/api/v1/categories")
      if(!response.ok){
        const errorMessage = `${response.status} (${response.statusText})`
        const error = new Error(errorMessage)
        throw(error);
      }
      const categoryData = await response.json();
      setCategories(categoryData.categories)
    } catch (error) {
      console.error(`Error in fetch: ${error.message}`)
    }
  }

  useEffect(() =>{
    fetchCategories()
  },[])

  const categoryLinks = categories.map(category =>{
    return(
      <li key={category.id} >
        <Link to={`/categories/${category.id}`}>{category.name}</Link>
      </li>
    )
  })

  categoryLinks.unshift(
    <li key={0}>
      <Link to={`/sites`} >Home</Link>
    </li>
  )

  return(
    <div>
      <div>
        <ul className="nav-link">
          {categoryLinks}
        </ul>
      </div>

      <Switch>
        <Route exact path="/" >
          <Redirect to="/sites" />
        </Route>
        <Route exact path="/sites" component={SitesIndex} />
        <Route exact path ="/sites/new" component={AddNewSiteForm} />
        <Route exact path="/sites/:id" component={SiteShow} />
        <Route exact path="/categories/:id" component={CategoryShow} />
      </Switch>
    </div>
  )

}

export default NavBar

【问题讨论】:

    标签: reactjs react-router react-link


    【解决方案1】:

    您应该包含您遇到问题的组件的代码。

    你知道你可以通过名为 useEffect 的特殊反应钩子监听所做的更改。 在您的类别组件中,您可以使用 props.match.params.id 作为 useEffect 依赖项并像这样监听更改

    const Categories = (props)=>{
     const id = props.match.params.id;
    useEffect(()=>{
      //do something 
    },[id])                     // This is where the react listens the changes
    
    }
    

    【讨论】:

      【解决方案2】:

      问题

      您没有包含有问题的代码,即 SiteShowCategoryShow,但我怀疑它们都没有对 id 路由匹配参数值的更改做出反应。

      解决方案

      SiteShowCategoryShow 中,使用依赖于id 路由匹配参数的useEffect 挂钩来更新任何状态、获取任何新数据等。

      import { useParams } from 'react-router-dom';
      
      ...
      
      const { id } = useParams();
      
      useEffect(() => {
        console.log('Route id updated', id);
        // logic to handle the id updating
      }, [id]);
      

      如果您仍在使用基于类的组件,请告诉我,我可以更新此用例的答案。

      关于使用Switch 的小点,您应该将您的路线从更具体的路径排序到不太具体的路径,这样您就不需要在每条路线上指定exact 属性。例如,“/sites/new”比“/sites/:id”更具体,比“/sites”更具体。 Redirect 也不应该也不应该被包裹在 Route 中。如果您需要从特定路径重定向,请使用 from 属性。

      <Switch>
        <Route path ="/sites/new" component={AddNewSiteForm} />
        <Route path="/sites/:id" component={SiteShow} />
        <Route path="/sites" component={SitesIndex} />
        <Route path="/categories/:id" component={CategoryShow} />
        <Redirect to="/sites" />
      </Switch>
      

      【讨论】:

        【解决方案3】:

        我最终使用 useLocation 来解决类别组件上的这个问题

        const CategoryShow = (props) =>{
          let location = useLocation();
          const [category, setCategory] = useState( {sites: []})
        
          const fetchCategory = async() => {
            try {
              const categoryId = props.match.params.id
              const response = await fetch(`/api/v1/categories/${categoryId}`)
              if(!response.ok) {
                const errorMessage = `${response.status} (${response.statusText})`
                const error = new Error(errorMessage)
                throw(err)
              }
              const categoryData = await response.json()
              setCategory(categoryData.category)
            } catch (err) {
              console.error(`Error in fetch: ${err.message}`)
              setCategory(null)
            }
          }
        
          useEffect(() =>{
            fetchCategory()
          },[location.pathname])
        
        
        
          if(!category) {
            return(
            <div>
              <h1>That category could not be found!</h1>
              <img src={"https://error404.fun/img/full-preview/1x/9.png"} height="100%" alt="Page Not Found" />
            </div>
            )
          }
        
          const siteTiles = category.sites.map(site =>{
            return(
              <SiteTile
              key = {site.id}
              site = {site}
              />
            )
          })
        
          return(
            <div>
              <h1>{category.name}</h1>
              {siteTiles}
            </div>
          )
        }
        
        export default CategoryShow
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-12-29
          • 2022-07-12
          • 1970-01-01
          • 2017-05-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多