我正在使用react-router-dom
构建一个React应用,并从Django Rest Framework后端获取数据,一旦获取数据,然后导航到另一个链接,该数据将保存到{{1}并保存在内部内部状态被删除。如何在客户端中保留这些数据?
这是代码:
window
Router
import React, { Component } from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import AuthHeader from './authheader';
import { BlogData, BlogDetail } from '../components/blog';
export default class AuthRouter extends Component {
constructor(props) {
super(props);
this.state = {
isLoggedIn: false,
authtoken: '',
}
}
handler = (token) => {
this.setState({
isLoggedIn: true,
authtoken: token,
})
}
/**
* ! Render the Route props inside of the
* ! BlogData component
*/
render () {
return (
<Router>
<div>
{/* <Header /> */}
{/* <Route path='/home' exact component={WrappedHorizontalLoginForm} /> */}
{/* <Route path='/about' exact component={AuthHeader} /> */}
<AuthHeader
action={this.handler}
token={this.state.isLoggedIn && this.state.authtoken}
/>
<Route
path='/blog'
exact
render={(props) => <BlogData {...props}
token={this.state.isLoggedIn && this.state.authtoken}
/>} />
<Route
path='/blog/:id'
exact
render={(props) => <BlogDetail {...props}
token={this.state.isLoggedIn && this.state.authtoken}
/>} />
</div>
</Router>
);
}
}
组件最终将道具向下传递到Authheader
:
LoginFormOrUserComponent
这是import React, { Component } from 'react';
import axios from 'axios';
import Button from 'react-bootstrap/Button';
import Form from 'react-bootstrap/Form';
import { localhost, authtoken } from '../backendUrlConstants';
import Col from 'react-bootstrap/Col';
export default class LoginFormOrUserComponent extends Component {
constructor(props) {
super(props);
this.state = {
isLoggedIn: false,
authtoken: null,
username: '',
password: '',
}
// if (this.props.token) {
// this.setState({ authtoken: this.props.token })
// this.setState({ isLoggedIn: true })
// }
}
// componentDidMount (props) {
// if (this.props.token) {
// this.setState({ authtoken: this.props.token })
// this.setState({ isLoggedIn: true })
// }
// }
passAuthTokenToParentClass = () => {
const { authtoken } = this.state;
if (authtoken) {
this.props.action(authtoken)
}
}
handleUsernameChange = (e) => {
this.setState({ username: e.target.value })
}
handlePasswordChange = (e) => {
this.setState({ password: e.target.value })
}
handleSubmit = (e) => {
console.log(e)
const username = this.state.username;
const password = this.state.password;
axios.post(`${localhost}${authtoken}`, { username, password })
.then(res => {
this.setState({ authtoken: res.data.token })
this.setState({ isLoggedIn: true })
this.passAuthTokenToParentClass()
})
// TODO: Catch the error if the username and password
// TODO: are incorrect.
}
renderLoginFormOrUserComponent = () => {
if (this.state.isLoggedIn === false) {
return <Form className="mr-auto" >
<Form.Row>
<Col xs={4}>
<Form.Control placeholder="Username" onChange={this.handleUsernameChange} />
</Col>
<Col xs={4}>
<Form.Control placeholder="Password" onChange={this.handlePasswordChange} />
</Col>
</Form.Row>
<Button variant="dark" onClick={this.handleSubmit} >Submit</Button>
</Form>
}
return <Button variant="dark" >Account</Button>
}
render () {
return (
this.renderLoginFormOrUserComponent()
);
}
}
和BlogData
组件:
BlogDetail
此外,在上下文中,这是我的本地Django服务器的URL:
import React, { Component } from 'react';
import axios from 'axios';
import { localhost } from '../backendUrlConstants';
import { Link } from 'react-router-dom';
import { Card } from 'react-bootstrap';
export class BlogData extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
}
}
getUrl () {
return this.props.location.pathname
}
componentDidMount () {
const uri = this.getUrl()
axios.get(`${localhost}${uri}`)
.then(res => {
const data = res.data;
this.setState({ data })
})
}
render () {
return (
<ul>
{this.state.data.map(
data => <li key={data.id} >
<Link to={`/blog/${data.id}`} >{data.url}</Link>
</li>
)}
</ul>
)
}
}
export class BlogDetail extends BlogData {
constructor(props) {
super(props)
this.state = {
blogObject: {}
}
}
componentDidMount () {
const uri = this.getUrl()
axios.get(`${localhost}${uri}`)
.then(res => {
const data = res.data;
this.setState({ blogObject: data })
})
}
render () {
const { blogObject } = this.state;
return (
<Card style={{ width: "18rem" }} >
<Card.Img variant="top" src={blogObject.blog_picture_context} />
<Card.Body>
<Card.Title>{blogObject.blog_name}</Card.Title>
<Card.Text>{blogObject.blog_post}</Card.Text>
</Card.Body>
</Card>
)
}
}
一旦我从后端获取数据,一旦导航到另一个页面,就会丢失它。显然我在这里缺少什么。
答案 0 :(得分:1)
使用钩子,您可以在导航到通常会刷新状态的新URL /链接时轻松传递数据。无需使用本地存储或类似的东西。
作为示例,我有一个管理仪表板,该仪表板具有嵌套的用户路由,我希望该用户的url为用户ID,并希望将该用户ID传递给新的url,并能够在其中使用新组件。
我的嵌套路由文件如下:
import React from 'react';
import { Index, SignIn, SignUp } from '../onepirate/';
import { Admin, Event, CheckoutPath, Profile, Tickets, CheckoutComplete } from '../screens/';
import AdminDashboard from '../components/admin/AdminDashboard';
import UserAccount from '../screens/admin/user-components/UserAccount'
import Users from '../screens/admin/Users';
const adminRoutes = {
"/dashboard": () => <AdminDashboard />,
"/events": () => <Event />,
"/users": () => <Users />,
"/users/:userId": ({ userId }) => <UserAccount userId={userId} />,
}
export default adminRoutes;
如您所见,我正在从/ users组件传递用户ID,并将其作为属性通过路由发送。同时,用户ID将动态添加到URL中。
然后将路由器导入到应该处理路由的组件中:
import { useRoutes, useRedirect, navigate } from 'hookrouter';
export default function Admin() {
// this function allows your to redirect from one URL to another
useRedirect('/admin', '/admin/dashboard');
return (
<main className={classes.content}>
<Container>
{router}
</Container>
</main>
</div>
);
}
然后以示例为例,从我的用户组件导航到users /:userID
import { useRoutes, useRedirect, navigate } from 'hookrouter';
const User = props => {
const classes = useStyles();
return (
<Container>
<Paper className={classes.root}>
<TextField
id="outlined-search"
label="Search field"
type="search"
className={classes.textField}
margin="normal"
variant="outlined"
onChange={props.search}
/>
<Table className={classes.table}>
<TableHead className={classes.tableHead}>
<TableRow className={classes.tableHead}>
<TableCell className={classes.tableHead} align="">Id</TableCell>
<TableCell className={classes.tableHead} align="">Email</TableCell>
<TableCell className={classes.tableHead} align="">First Name</TableCell>
<TableCell className={classes.tableHead} align="">Last Name</TableCell>
<TableCell className={classes.tableHead} align="">Info</TableCell>
</TableRow>
</TableHead>
<TableBody>
{props.data.map((user, index) => (
<TableRow key={index}>
<TableCell align="right">{user.id}</TableCell>
<TableCell align="right">{user.email}</TableCell>
<TableCell align="right">{user.firstname}</TableCell>
<TableCell align="right">{user.lastname}</TableCell>
// be sure to pass the user id in the navigate() function
<TableCell><AccountBoxIcon onClick={() => (navigate("/admin/users/" + user.id))}></AccountBoxIcon></TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Paper>
</Container>
)
}
export default User;
然后在UserAccount组件中将其链接到我们的路由文件中,并将用户ID传递到,我们可以看到控制台将在propE中的道具记录在useEffect(组件将挂载等高线)钩子中传递的数据。
// UserAccount组件:
useEffect(() => {
// userId we sent as prop through route
console.log(props.userId);
// ... do cool things
}, []);
答案 1 :(得分:0)
好,所以这是用于将数据持久存储在本地存储中的代码。
import React, { Component } from 'react';
import axios from 'axios';
import Button from 'react-bootstrap/Button';
import Form from 'react-bootstrap/Form';
import { localhost, authtoken } from '../backendUrlConstants';
import Col from 'react-bootstrap/Col';
export default class LoginFormOrUserComponent extends Component {
constructor(props) {
super(props);
this.state = {
isLoggedIn: false,
authtoken: null,
username: '',
password: '',
}
// if (this.props.token) {
// this.setState({ authtoken: this.props.token })
// this.setState({ isLoggedIn: true })
// }
}
componentDidMount (props) {
const storage = window.localStorage
const status = storage.getItem('isLoggedIn')
if (status) {
this.setState({ isLoggedIn: true })
this.setState({ authtoken: storage.getItem('token') })
}
}
hanldeClick = (e) => {
this.setState({ isLoggedIn: false })
this.setState({ authtoken: null })
const storage = window.localStorage
storage.clear()
}
passAuthTokenToParentClass = () => {
const { authtoken } = this.state;
if (authtoken) {
this.props.action(authtoken)
}
}
handleUsernameChange = (e) => {
this.setState({ username: e.target.value })
}
handlePasswordChange = (e) => {
this.setState({ password: e.target.value })
}
handleSubmit = (e) => {
const storage = window.localStorage
const username = this.state.username;
const password = this.state.password;
axios.post(`${localhost}${authtoken}`, { username, password })
.then(res => {
// ! persist the data in localstorage =>
storage.setItem('token', res.data.token)
storage.setItem('isLoggedIn', true)
this.setState({ isLoggedIn: true })
this.setState({ authtoken: res.data.token })
console.log(storage)
})
// TODO: Catch the error if the username and password
// TODO: are incorrect.
}
renderLoginFormOrUserComponent = () => {
if (this.state.isLoggedIn === false) {
return <Form className="mr-auto" >
<Form.Row>
<Col xs={4}>
<Form.Control placeholder="Username" onChange={this.handleUsernameChange} />
</Col>
<Col xs={4}>
<Form.Control placeholder="Password" onChange={this.handlePasswordChange} />
</Col>
</Form.Row>
<Button variant="dark" onClick={this.handleSubmit} >Submit</Button>
</Form>
}
return <Button variant="dark" onClick={this.hanldeClick} >Account</Button>
}
render () {
return (
this.renderLoginFormOrUserComponent()
);
}
}
'''
I also added a logout button to clear the data kept in `localStorage` when the user clicks the Account button.