简体   繁体   English

登录后和异步调用后,React重新渲染

[英]React re-render after login — and after an asynchronous call

In my Login react component here, I call handleLogin within the handleSubmit method. 在此处的Login react组件中,我在handleSubmit方法中调用handleLogin And then... (see below)... 然后...(见下文)...

import React from "react"
import { Redirect } from "react-router-dom"
import axios from 'axios'
import Form from "./Form"
import View from "./View"
import { handleLogin, isLoggedIn } from "../utils/auth"

export default class Login extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      email: ``,
      password: ``,
    };
  }

  handleUpdate(event) {
    this.setState({
      [event.target.name]: event.target.value,
    })
  }

  handleSubmit(event) {
    event.preventDefault()
    handleLogin(this.state)
  }

  render() {
    if (isLoggedIn()) {
      return <Redirect to={{ pathname: `/app/profile` }} />
    }

    return (
      <View title="Log In">
        <Form
          handleUpdate={e => this.handleUpdate(e)}
          handleSubmit={e => this.handleSubmit(e)}
        />
      </View>
    )
  }
}

...Within the handleLogin method (imported from ../utils/auth below), I make an asynchronous call ( axios.post ): ...在handleLogin方法(从下面的../utils/auth导入)中,我进行了异步调用( axios.post ):

// in /utils/auth.js

import axios from 'axios'

const isBrowser = typeof window !== `undefined`

const getUser = () =>
  window.localStorage.gatsbyUser
    ? JSON.parse(window.localStorage.gatsbyUser)
    : {}

const setUser = user => (window.localStorage.gatsbyUser = 
JSON.stringify(user))

export const handleLogin = ({ email, password }) => {
  if (!isBrowser) return false

  axios.post(`${process.env.API_URL}/sessions`, {
    email: email,
    password: password,
  })
  .then(response => {
    console.log(response);
    return setUser({
      name: `Jim`,
      legalName: `James K. User`,
      email: email,
    })
  })
  .catch(error => {
    return false
  });
}

export const isLoggedIn = () => {
  if (!isBrowser) return false

  const user = getUser()
  return !!user.email
}

The problem I run into is that the render() method is called before the axios.post / handleLogin(this.state) is resolved, thus preventing the render() method from seeing the isLoggedIn() as returning true . 我遇到的问题是在解决axios.post / handleLogin(this.state)之前调用了render()方法,从而阻止了render()方法将isLoggedIn()视为返回true

I'd like to know how I can prevent the render() method from being called before axios.post is resolved. 我想知道如何防止axios.post解决之前调用render()方法。

You can solve this problem by triggering a re-render. 您可以通过触发重新渲染来解决此问题。 Based on your code example, I reckon you just need to wait for the handleLogin async call to finish, then check if user is logged or not with isUserLogin , you should add a local state that is mirrored isUserLogin to trigger the re-render. 根据您的代码示例,我认为您只需要等待handleLogin异步调用完成,然后使用isUserLogin检查用户是否已登录,则应添加镜像isUserLogin的本地状态以触发重新渲染。

Below is an example using Promise, you can achieve the same thing with async/await: 以下是使用Promise的示例,您可以使用async / await实现相同的功能:

export default class Login extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      email: ``,
      password: ``,
      isLoggedIn: false
    };
  }

  handleSubmit(event) {
    event.preventDefault()
    handleLogin(this.state)
      .then(response => this.setState({isLoggedIn: isLoggedIn()}))
      .catch(err => // Handle the error here, or just swallow it)
  }

  render() {
    if (this.state.isLoggedIn) {
      return <Redirect to={{ pathname: `/app/profile` }} />
    }

    return (
      <View title="Log In">
        <Form
          handleUpdate={e => this.handleUpdate(e)}
          handleSubmit={e => this.handleSubmit(e)}
        />
      </View>
    )
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM