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