obabichev / react-token-auth

84 stars 22 forks source link

Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function. #9

Open UseMuse opened 4 years ago

UseMuse commented 4 years ago

Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function. in SignIn (at PublicRoute.js:24)

import React, { useContext } from 'react'
import ConfigContext from '../../providers/Config/Context'
import { Route, Redirect, useHistory} from 'react-router-dom'

function PublicRoute({ component: Component, redirectTo = '/', ...rest }) {
    const { appConfig } = useContext(ConfigContext)
    const { auth } = appConfig || {}
    const { useAuth } = auth || {}
    const [isAuthorised] = useAuth()
    const history = useHistory()
    let _location = history.location

    if (isAuthorised) {
        if (_location.state && _location.state.from) {
            redirectTo = redirectTo === '/' ? _location.state.from.pathname : redirectTo
        }
    }

    return (
        <Route
            {...rest}
            render={(props) =>
              /* тут ошибка */  !isAuthorised ? (
                    <Component {...props} />
                ) : (
                        <Redirect
                            to={{
                                pathname: redirectTo,
                                search: `from=${props.location.pathname}`,
                                state: { from: props.location },
                            }}
                        />
                    )
            }
        />
    )
}

export default PublicRoute
UseMuse commented 4 years ago

не знаю как профиксить ошибку, строка с ошибкой помечена комментарием / тут ошибка /. Все продолжает работать, но, ошибка красным текстом в консоли не даёт мне покоя. Нужно наверное что-то сделать на странице SignIn в useEffect.

UseMuse commented 4 years ago

После того, как я успешно авторизуюсь, меня переводит на домашнюю страницу и тогда я имею эту ошибку в консоли

UseMuse commented 4 years ago
//import { saveAuthorisation, isAuthorised } from '../../utils/auth'
import { useIntl } from 'react-intl'
import Page from '../../containers/Page/Page'
import React, { useState, useContext, useRef, useEffect } from 'react'
import { makeStyles } from '@material-ui/core/styles'
import { Paper, Button, Typography, TextField, Link, Box } from '@material-ui/core'
import ConfigContext from '../../providers/Config/Context'
import MenuContext from '../../providers/Menu/Context'
import ReCAPTCHA from "react-google-recaptcha";
import OnlineContext from '../../providers/Online/Context'

const useStyles = makeStyles((theme) => ({
    paper: {
        width: 'auto',
        marginLeft: theme.spacing(3),
        marginRight: theme.spacing(3),
        [theme.breakpoints.up(620 + theme.spacing(6))]: {
            width: 400,
            marginLeft: 'auto',
            marginRight: 'auto'
        },
        marginTop: theme.spacing(8),
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
        padding: `${theme.spacing(2)}px ${theme.spacing(3)}px ${theme.spacing(3)}px`
    },
    avatar: {
        margin: theme.spacing(1),
        width: 192,
        height: 192,
        color: theme.palette.secondary.main,
    },
    form: {
        marginTop: theme.spacing(1),
    },
    submit: {
        margin: theme.spacing(3, 0, 2),
    },
    container: {
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'center',
        height: `100%`,
    },
}))

const SignIn = () => {
    const isOnline = useContext(OnlineContext)
    const [message, setMessage] = useState(false);
    const [hasError, setError] = useState(false);

    const [isLoading, setLoading] = useState(false);
    const recaptchaRef = useRef({});

    const classes = useStyles()
    const intl = useIntl()

    const { appConfig } = useContext(ConfigContext)
    const { login, key } = appConfig.auth;

    const [credentials, setCredentials] = useState({
        username: '',
        password: ''
    });
    const [changes, setChanges] = useState(false);
    const { setAuthMenuOpen } = useContext(MenuContext)
    const onChange = ({ target: { name, value } }) => {
        setChanges(true)
        setCredentials(Object.assign(Object.assign({}, credentials), { [name]: value }));
    };

    const putError = (msg) => {
        setError(true);
        setMessage(msg);
    }
    const resetMsg = () => {
        setError(false);
        setMessage("");
    }
    const resetCa = () => {
        if (recaptchaRef && recaptchaRef.current && recaptchaRef.current.reset) {
            recaptchaRef.current.reset()
        }
    }

    const verifyCallback = function (value) {
        if (!changes) { setLoading(false);  return; }
        //try {
            fetch('./api/Auth/authenticate', {
                method: 'post',
                headers: {
                    'Content-Type': 'application/json',
                    'g-recaptcha-response': value
                },
                body: JSON.stringify(credentials)
            })
                .then(response => {
                    if (response.status === 202) {
                        resetMsg()
                        return response.json()
                    }
                    else {
                        return Promise.reject(response)
                    }
                })
                .then(token => {
                    authenticate(token);
                }).catch((e) => {
                    if (e.status === 400) {
                        putError("Вы не прошли валидацию reCAPTCHA, попробуйте снова")
                    }
                    else if (e.status === 401) {
                        putError("Неправильное имя пользователя или пароль")
                    }
                    else if (e.status === 555) {
                        putError("Служба каталогов недоступна. Пожалуйста, обратитесь к администратору сети")
                    }
                    else if (e.status > 401) {
                        putError("Ошибка авторизации")
                    }
                    setLoading(false)
                    resetCa();
                    setChanges(false)
                });
        //} catch (e) {
        //    putError("Ошибка авторизации")
        //    setLoading(false)
        //    resetCa();
        //    resetMsg();
        //    setChanges(false)
        //    throw e
        //}

    };

    const onSubmit = (event) => {
        resetMsg();
        if (event) {
            event.preventDefault();
        }
        setLoading(true)
        try {
            recaptchaRef.current.execute()
        } catch (e) {
            console.error('onSubmit', e);
        }

    }

    const authenticate = (token) => {
        login(token)
        setAuthMenuOpen(false)
        setLoading(false)
        resetCa();
        setChanges(false)
        resetMsg();
    }

    return (
        <Page pageTitle={intl.formatMessage({ id: 'sign_in' })} isLoading={isLoading}>
            <Paper className={classes.paper} elevation={6}>
                <div className={classes.container}>
                    <Typography component="h1" variant="h5">
                        {intl.formatMessage({ id: 'sign_in' })}
                    </Typography>
                    <form className={classes.form} onSubmit={onSubmit}>
                        <ReCAPTCHA
                            ref={recaptchaRef}
                            size="invisible"
                            sitekey={key}
                            onChange={verifyCallback}
                        />
                        <TextField
                            value={credentials.username}
                            onInput={onChange}
                            variant="outlined"
                            margin="normal"
                            required
                            fullWidth
                            id="username"
                            label={intl.formatMessage({ id: 'username' })}
                            name="username"
                            autoComplete="username"
                            autoFocus
                            disabled={isLoading || !isOnline}
                        />
                        <TextField
                            value={credentials.password}
                            onInput={onChange}
                            variant="outlined"
                            margin="normal"
                            required
                            fullWidth
                            name="password"
                            label={intl.formatMessage({ id: 'password' })}
                            type="password"
                            id="password"
                            autoComplete="current-password"
                            disabled={isLoading || !isOnline}
                        />
                        <Button
                            type="submit"
                            fullWidth
                            variant="contained"
                            color="primary"
                            className={classes.submit}
                            disabled={isLoading || !isOnline}>
                            {intl.formatMessage({ id: 'sign_in' })}
                        </Button>
                        <Box visibility={hasError ? 'visible' : 'hidden'} color='error.main' fontSize={12} align="justify">
                            {message}
                        </Box>
                        <Box color="text.disabled" fontSize={12} align="justify">
                            Этот сайт защищен reCAPTCHA и Google.<br />
                            <Link underline="hover" color="textSecondary" href="https://policies.google.com/privacy"> Политика конфиденциальности </Link>,
    применяются <Link color="textSecondary" underline="hover" href="https://policies.google.com/terms"> Условия использования </Link>.
                        </Box>
                    </form>
                </div>
            </Paper>

        </Page>
    )
}

export default SignIn
UseMuse commented 4 years ago

эта ошибка возникает один раз, когда я впервые авторизуюсь временно пришлось отказаться от хука useAuth в пользу isLoggedIn()

Tooluloope commented 4 years ago

make a reproduction on codesandbox

naishal commented 3 years ago

Hello @UseMuse if you have solved the problem please guide me through...I also get same error and now no other page in my application opens up due to this error... Thanks in advance.

UseMuse commented 3 years ago

@Tooluloope @naishal @obabichev

make a reproduction on codesandbox

https://codesandbox.io/s/react-material-ui-forked-jvl0h look at the error in the console