В моем компоненте реакции 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.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете решить эту проблему, запустив повторный рендеринг. Основываясь на вашем примере кода, я считаю, вам просто нужно дождаться завершения асинхронного вызова 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, это проблема с вашей функцией handleLogin. По сути, к тому времени, когда будет запущен ответ then, handleLogin уже должен быть решен. Проблема в том, что вы ничего не возвращаете из своей функции handleLogin, поэтому ее тип возврата не определен. Вы должны обновить его, чтобы вернуть функцию axios: return axios.post(...)
Я вижу, что добавление return к axios позволяет вернуть handleLogin(this.state). Спасибо!
Этот вид функциональности должен обрабатываться компонентами более высокого порядка, если вам действительно нужен способ работы React. Таким образом, вы можете «предотвратить» вызов метода рендеринга. Во-вторых, состояние входа в систему (получить ?!) вашего приложения должно / может быть сохранено в состоянии и доступно для всех дочерних компонентов (которые в этом случае будут в основном всем вашим приложением).