Реагировать на повторный рендеринг после входа в систему - и после асинхронного вызова

В моем компоненте реакции Login здесь я вызываю handleLogin в методе handleSubmit. А потом ... (см. Ниже) ...

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>
    )
  }
}

... В методе 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.info(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
}

Проблема, с которой я столкнулся, заключается в том, что метод render() вызывается до разрешения axios.post / handleLogin(this.state), что не позволяет методу render() видеть isLoggedIn() как возвращающий true.

Я хотел бы знать, как я могу предотвратить вызов метода render() до разрешения axios.post.

Этот вид функциональности должен обрабатываться компонентами более высокого порядка, если вам действительно нужен способ работы React. Таким образом, вы можете «предотвратить» вызов метода рендеринга. Во-вторых, состояние входа в систему (получить ?!) вашего приложения должно / может быть сохранено в состоянии и доступно для всех дочерних компонентов (которые в этом случае будут в основном всем вашим приложением).

Abid Hasan 30.05.2018 02:06
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
1
1 954
1

Ответы 1

Вы можете решить эту проблему, запустив повторный рендеринг. Основываясь на вашем примере кода, я считаю, вам просто нужно дождаться завершения асинхронного вызова handleLogin, затем проверить, зарегистрирован ли пользователь или нет с помощью isUserLogin, вы должны добавить локальное состояние, которое является зеркальным отражением isUserLogin, чтобы запустить повторный рендеринг.

Ниже приведен пример использования 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>
    )
  }
}

Когда я попробовал это, handleLogin(this.state) возвращает undefined, поэтому я получаю ошибку TypeError: Cannot read property 'then' of undefined - даже после того, как я добавил .then(response => {return isLoggedIn()}) к методу handleLogin. Асинхронный вызов в handleLogin не разрешается вовремя, чтобы предоставить возвращаемое значение, когда он вызывается в handleSubmit.

Matt 30.05.2018 15:38

@matt, это проблема с вашей функцией handleLogin. По сути, к тому времени, когда будет запущен ответ then, handleLogin уже должен быть решен. Проблема в том, что вы ничего не возвращаете из своей функции handleLogin, поэтому ее тип возврата не определен. Вы должны обновить его, чтобы вернуть функцию axios: return axios.post(...)

Thai Duong Tran 31.05.2018 02:43

Я вижу, что добавление return к axios позволяет вернуть handleLogin(this.state). Спасибо!

Matt 31.05.2018 03:47

Другие вопросы по теме