Reactjs 从动态路由到静态路由时,组件不会更改状态

Reactjs 从动态路由到静态路由时,组件不会更改状态,reactjs,Reactjs,我有一个route/users打印用户列表,每个用户都是指向显示用户详细信息的动态route/users/:cn的链接。 可以从/users导航到/users/:cn,但是从/users/:cn导航到/users是不可能的,url会更改,但什么也不会发生,并且在后端日志中没有对/users页面的get请求。但是,如果我在/users/:cn上导航到/otherRoute,它可以正常工作,或者如果我在/users上导航到/otherRoute也可以正常工作。我想当我在动态路线上时,我需要以某种方式

我有一个route
/users
打印用户列表,每个用户都是指向显示用户详细信息的动态route
/users/:cn
的链接。 可以从
/users
导航到
/users/:cn
,但是从
/users/:cn
导航到
/users
是不可能的,url会更改,但什么也不会发生,并且在后端日志中没有对
/users
页面的get请求。但是,如果我在
/users/:cn
上导航到
/otherRoute
,它可以正常工作,或者如果我在
/users
上导航到
/otherRoute
也可以正常工作。我想当我在动态路线上时,我需要以某种方式更新状态。有什么帮助吗

我已经试过用路由器包装组件
userWrapper
,但是没有用

users.js

import React ,{Component} from "react"
import { BrowserRouter as Router,Switch, Route, withRouter} from "react-router-dom"
import Layout from "../components/layout"
import User from "../components/users"
import MainComponentWrapper from "../components/mainComponentWrapper"
import UserDetails from "../components/userDetails"


const userDetailsWrapper = props => {
  const url = "http://localhost:5000/user/" + props.match.params.cn
  return (
    <MainComponentWrapper url={url}>
      <UserDetails />
    </MainComponentWrapper>
  )
}

const userWrapper = props => {

  const url = "http://localhost:5000/user"
  return (
    <MainComponentWrapper url={url}>
      <User />
    </MainComponentWrapper>
  )
}


const IndexPage = () => (
      <div>
    <Router >
       <Layout>
         <Switch>

               <Route exact path="/users" component={(userWrapper)}/>
               <Route exact path="/users/:cn"  component={userDetailsWrapper} />

           </Switch>
        </Layout>
    </Router>
 </div>

)


export default IndexPage

import React,{Component}来自“React”
从“react Router dom”导入{BrowserRouter as Router,Switch,Route,withRouter}
从“./组件/布局”导入布局
从“./组件/用户”导入用户
从“./components/MainComponentWrapper”导入MainComponentWrapper
从“./components/UserDetails”导入用户详细信息
const userDetailsWrapper=props=>{
常量url=”http://localhost:5000/user/“+props.match.params.cn
返回(
)
}
const userWrapper=props=>{
常量url=”http://localhost:5000/user"
返回(
)
}
常量索引页=()=>(
)
导出默认索引扩展
layout.jsx

import PropTypes from "prop-types"
import React from "react"
import { makeStyles } from "@material-ui/core/styles"
import Drawer from "@material-ui/core/Drawer"
import CssBaseline from "@material-ui/core/CssBaseline"
import List from "@material-ui/core/List"
import Divider from "@material-ui/core/Divider"
import ListItem from "@material-ui/core/ListItem"
import ListItemIcon from "@material-ui/core/ListItemIcon"
import ListItemText from "@material-ui/core/ListItemText"
import ExitToApp from "@material-ui/icons/ExitToApp"
import PeopleIcon from "@material-ui/icons/People"
import ListIcon from "@material-ui/icons/List"
import ComputerIcon from "@material-ui/icons/Computer"
import { navigate } from "gatsby"



const drawerWidth = 240

const useStyles = makeStyles(theme => ({
  root: {
    display: "flex",
  },
  appBar: {
    zIndex: theme.zIndex.drawer + 1,
  },
  drawer: {
    width: drawerWidth,
    flexShrink: 0,
  },
  drawerPaper: {
    width: drawerWidth,
  },
  content: {
    flexGrow: 1,
    padding: theme.spacing(3),
  },
  toolbar: theme.mixins.toolbar,
}))

function Layout({ children }) {

  const classes = useStyles()



  const handleLogout = event => {
    localStorage.removeItem("access_token")
    window.location.replace("/")
  }
  return (
    <div className={classes.root}>
      <CssBaseline />
      <Drawer
        className={classes.drawer}
        variant="permanent"
        classes={{
          paper: classes.drawerPaper,
        }}
      >
        <div className={classes.toolbar} />
        <List>
          <ListItem button onClick={() => navigate("/users")}>
            <ListItemIcon>
              <PeopleIcon />
            </ListItemIcon>
            <ListItemText primary={"Users"} />
          </ListItem>
          <ListItem button onClick={() => navigate("/machines")}>
            <ListItemIcon>
              <ComputerIcon />
            </ListItemIcon>
            <ListItemText primary={"Machines"} />
          </ListItem>
          <ListItem button onClick={() => navigate("/audits")}>
            <ListItemIcon>
              <ListIcon />
            </ListItemIcon>
            <ListItemText primary={"Audit"} />
          </ListItem>
        </List>
        <Divider />
        <List>
          <ListItem button onClick={handleLogout}>
            <ListItemIcon>
              <ExitToApp />
            </ListItemIcon>
            <ListItemText primary={"Logout"} />
          </ListItem>
        </List>
      </Drawer>
      <main className={classes.content}>
        <div className={classes.toolbar} />
        {children}
      </main>
    </div>
  )
}

Layout.propTypes = {
  children: PropTypes.node.isRequired,
}

export default Layout
从“道具类型”导入道具类型
从“React”导入React
从“@material ui/core/styles”导入{makeStyles}”
从“@material ui/core/Drawer”导入抽屉
从“@material ui/core/CssBaseline”导入CssBaseline
从“@material ui/core/List”导入列表
从“@material ui/core/Divider”导入分隔器
从“@material ui/core/ListItem”导入ListItem
从“@material ui/core/ListItemIcon”导入ListItemIcon
从“@material ui/core/ListItemText”导入ListItemText
从“@material ui/icons/ExitToApp”导入ExitToApp
从“@material ui/icons/People”导入人物图标
从“@material ui/icons/List”导入ListIcon
从“@material ui/icons/Computer”导入计算机图标
从“盖茨比”导入{navigate}
常数抽屉宽度=240
const useStyles=makeStyles(主题=>({
根目录:{
显示:“flex”,
},
appBar:{
zIndex:theme.zIndex.drawer+1,
},
出票人:{
宽度:抽屉宽度,
flexShrink:0,
},
抽屉纸:{
宽度:抽屉宽度,
},
内容:{
flexGrow:1,
填充:主题。间距(3),
},
工具栏:theme.mixins.toolbar,
}))
函数布局({children}){
常量类=useStyles()
const handleLogout=事件=>{
localStorage.removietem(“访问令牌”)
window.location.replace(“/”)
}
返回(
导航(“/users”)}>
导航(“/machines”)}>
导航(“/audits”)}>
{儿童}
)
}
Layout.propTypes={
子项:PropTypes.node.isRequired,
}
导出默认布局
MainComponentWrapper.jsx

import React from "react"
import { makeStyles } from "@material-ui/core/styles"
import CircularProgress from "@material-ui/core/CircularProgress"

const useStyles = makeStyles(theme => ({
  root: {
    width: "100%",
  },
  progress: {
    margin: theme.spacing(2),
  },
}))

export default function MainComponentWrapper({ url, children }) {
  const classes = useStyles()
  const [data, setData] = React.useState()

  React.useEffect(() => {
    fetch(url, {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
        Authorization: "Bearer " + window.localStorage.getItem("access_token"),
      },
    })
      .then(resp => {
        return resp.json()
      })
      .then(fetchedData => {
        setData(fetchedData)
      })
      .catch(error => {
        console.log(error)
         window.localStorage.removeItem("access_token")
         window.location.replace("/")
      })
  }, [url])
  if (data === undefined) {
    return (
      <div className={classes.root}>
        <CircularProgress className={classes.progress} />
      </div>
    )
  }

  return (
    <div className={classes.root}>
      {React.cloneElement(children, { data: data })}
    </div>
  )
}

从“React”导入React
从“@material ui/core/styles”导入{makeStyles}”
从“@material ui/core/CircularProgress”导入CircularProgress
const useStyles=makeStyles(主题=>({
根目录:{
宽度:“100%”,
},
进展:{
边距:主题。间距(2),
},
}))
导出默认函数MainComponentWrapper({url,children}){
常量类=useStyles()
const[data,setData]=React.useState()
React.useffect(()=>{
获取(url{
方法:“获取”,
标题:{
“内容类型”:“应用程序/json”,
授权:“载体”+window.localStorage.getItem(“访问令牌”),
},
})
。然后(resp=>{
return resp.json()
})
。然后(fetchedData=>{
设置数据(获取数据)
})
.catch(错误=>{
console.log(错误)
window.localStorage.removietem(“访问令牌”)
window.location.replace(“/”)
})
},[url])
如果(数据===未定义){
返回(
)
}
返回(
{React.cloneElement(子项,{data:data})}
)
}

使用@reach/router而不是react router dom为作者解决了这个问题。用于导航页面的盖茨比库是在@reach/router上构建的,因此使用react-router-dom会导致冲突。@react/router的代码更改

从“@reach/Router”导入{Router}
...
阅读评论了解详情。以下是作者的答案

已丢弃


一切似乎都很好,请您也分享您的
的代码。你是如何调用API的?具体是在哪个生命周期方法中?

所以我解决了这个问题,@m.sohail是对的。 我使用
react router dom
时发生冲突,我需要使用
@reach/router
,并进行了一些代码更改

import React from "react"
import Layout from "../components/layout"
import User from "../components/users"
import MainComponentWrapper from "../components/mainComponentWrapper"
import UserDetails from "../components/userDetails"
import { Router } from "@reach/router"

const IndexPage = () => (
  <div>
    <Layout>
      <Router>
        <UserWrapper path="/users" />
        <UserDetailsWrapper path="/users/:cn" />
      </Router>
    </Layout>
  </div>
)
从“React”导入React
从“./组件/布局”导入布局
从“./组件/用户”导入用户
从“./components/MainComponentWrapper”导入MainComponentWrapper
从“./components/UserDetails”导入用户详细信息
从“@reach/Router”导入{Router}
常量索引页=()=>(
)

这是因为您的URL是
”http://localhost:5000/user“
而不是
”http://localhost:5000/users“
?如果这不是问题,你能制作一个可拆卸的版本吗
import React from "react"
import Layout from "../components/layout"
import User from "../components/users"
import MainComponentWrapper from "../components/mainComponentWrapper"
import UserDetails from "../components/userDetails"
import { Router } from "@reach/router"

const IndexPage = () => (
  <div>
    <Layout>
      <Router>
        <UserWrapper path="/users" />
        <UserDetailsWrapper path="/users/:cn" />
      </Router>
    </Layout>
  </div>
)