React Router:导航到新路线时,使用axios提取的数据不会保存

时间:2019-11-18 03:34:51

标签: javascript reactjs react-router-dom

我正在使用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>
        )
    }
}

一旦我从后端获取数据,一旦导航到另一个页面,就会丢失它。显然我在这里缺少什么。

2 个答案:

答案 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.