Компонент React не отображается после проверки подлинности

#javascript #reactjs #react-hooks #jsx #react-component

#javascript #reactjs #реагирующие крючки #jsx #реагирующий компонент

Вопрос:

Итак, в основном я пытаюсь создать защищенный маршрут для своего приложения, и у меня есть другая функция, которая проверяет с помощью API сервера, правильно ли аутентифицирован клиент. К сожалению, из-за того, как работают перехватчики React, состояние не обновляется напрямую, и если я пытаюсь перенаправить, когда пользователь не аутентифицирован, он просто отправляет меня туда. Поэтому, когда вы перезагружаете страницу, поскольку состояние также сбрасывается, при первом рендеринге он будет относиться ко мне так, как будто я не вошел в систему (хотя я есть) и отправляю меня на страницу входа.

Итак, я подумал, что могу подождать, пока он не получит ответ, а затем выполнить рендеринг isAuth(ctx).then(...) , однако он просто ничего не отображает.

Вот структура маршрутизатора, которая у меня есть:

     <BrowserRouter>
        <AppContext.Provider value={ctx}>
            <Route path="/dashboard">
                <Switch>
                    <LoginRoute exact path="/dashboard/login" component={LogInDash} />
                    <ProtectedRoute exact path="/dashboard/create" component={CreateProperty} />
                    <ProtectedRoute exact path="/dashboard/list" component={ListDash} />
                    <ProtectedRoute exact path="/dashboard/edit/:id" component={EditProperty} />
                    <ProtectedRoute exact path="/dashboard/delete/:id" component={DeleteProperty} />
                </Switch>
            </Route>
        </AppContext.Provider>
    </BrowserRouter>
  

И вот функция для извлечения из API:

 export const isAuth = async (ctx: React.ComponentState): Promise<boolean> => {
const fetchRes = fetch(`${APIURL}/api/auth`, {
    method: 'GET',
    headers: { 'Content-Type': 'application/json' },
    credentials: 'include',
})
    .then((res) => {
        res.json();
        if (res.status === 200) {
            ctx.auth.set(true);
            console.log('successful verification');
            return true;
        } else {
            ctx.auth.set(false);
            console.log('Token not verified');
            return false;
        }
    })
    .catch((error) => {
        console.log(error);
        return false;
    });
return fetchRes;
  

};

И, наконец, вот код ProtectedRouter:

 export function ProtectedRoute({ component: Component, ...rest }: any): any {
    const ctx = React.useContext(AppContext);
    return (
        <Route
            {...rest}
            render={(props) => {
                isAuth(ctx);
                /* isAuth(ctx).then((res) => { */
                if (ctx.auth.get) {
                    return <Component {...rest} {...props} />;
                } else {
                    /* return <Unauthorized />; */
                    return <Redirect to="/dashboard/login" />;
                    /* window.location.href = '/dashboard/login'; */
                }
                /* }); */
            }}
        />
    );
}
  

Я чувствую, что просто упускаю что-то глупое или есть какая-то ошибка в концепции, которую я пытаюсь применить.

Спасибо, что даже прочитали это далеко!

Ответ №1:

Я бы ввел новое isReady состояние и await для аутентификации внутри useEffect перехвата. Например, пока он не будет готов, приложение может отображать загрузку <span> .

Смотрите на мое предложение следующим образом:

 export function ProtectedRoute({ component: Component, ...rest }: any): any {
    const ctx = React.useContext(AppContext);
    const [isReady, setIsReady] = useState(false);

    useEffect(() => {
       const runAuth = async () => {
           await isAuth(ctx);
           setIsReady(true);
       }

       runAuth();
    }, [])

    return (
        <Route
            {...rest}
            render={(props) => {
                if (!isReady} {
                   return <span>Loading ...</span>
                }

                if (ctx.auth.get) {
                    return <Component {...rest} {...props} />;
                } else {
                    /* return <Unauthorized />; */
                    return <Redirect to="/dashboard/login" />;
                    /* window.location.href = '/dashboard/login'; */
                }
                /* }); */
            }}
        />
    );
}
  

Предлагаемое чтение использует перехват эффекта.

Комментарии:

1. Это сработало как шарм, добавление новой переменной состояния и использование useEffect сделали свое дело. Я думал о способе реализации асинхронной функции, к которой также был доступ ctx , и не думал об использовании useEffect … Большое спасибо!!

2. @Belf Потрясающе, рад помочь!

Ответ №2:

 // NOTE: Is this firing correctly.. doesn't seem to fire if signed in .... and then try to go to profile or inventory page directly .... always redirects to '/' it seems
const AuthedRoute = ({ component: Component, user, ...rest }) => (
    <Route
        {...rest}
        render={(props) =>
          user.authenticated === null ? null : user.authenticated ? <Component {...props} /> : <Redirect to="/" />
        }
    />
);