質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

2回答

2764閲覧

React routerによる認証時のにリロードした際のルーティング

it-tsumugi

総合スコア11

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2021/09/17 15:29

編集2021/09/18 03:04

#現在やっていること
React Typescript laravel styled-componentsでtodoリストのポートフォリオを作成しています

#解決したいこと
ログイン時と非ログイン時でガードのようなものをしてリロードしてもログイン状態を維持するようにプログラムしているのですが、ログイン状態でhome以外のページでリロードを行うとhomeにリダイレクトしてしまいます。ログイン時のそのページがそのまま表示されてほしいです

#考えられそうな原因
ログイン状態の取得はリロードする度にlaravelにapiで問い合わせており、ログインしていなかったらログイン画面に、逆にログインしているのにログイン画面にアクセスしようとしたらhomeにリダイレクトするようにガードで実現しています。コンソールで見ている感じ何回もログイン情報を取りに行っているため、この2つを行き来している可能性があるのですがどうすればリダイレクト前に確実にログイン情報を手に入れられるのかよく分かりません。これが原因かは分かりませんが、自分の考えだけ載せておきます

どなたかリロードした際にそのままのページが表示されるやり方を教えていただけると助かります。

ComponentRouter.tsx

import { VFC } from "react"; import { BrowserRouter, Route, Switch, Redirect } from "react-router-dom"; import styled from "styled-components"; import { Login } from "../components/pages/Login"; import { Home } from "../components/pages/logined/Home"; import { Top } from "../components/pages/Top"; import { Register } from "../components/pages/Register"; import { AuthRoute } from "./AuthRoute"; import { GuestRoute } from "./GuestRoute"; import { DefaultLayout } from "../components/templates/DefaultLayout"; import { LoginedLayout } from "../components/templates/LoginedLayout"; import { AddGroup } from "../components/pages/logined/action/AddGroup"; import { Quadrant } from "../components/pages/logined/Quadrant"; import { Group } from "../components/pages/logined/Group"; import { Edit } from "../components/pages/logined/action/Edit"; import { Help } from "../components/pages/Help"; import { path } from "../assets/data/path"; import { AddTask } from "../components/pages/logined/action/AddTask"; import { ActionLayout } from "../components/templates/ActionLayout"; export const ComponentRouter: VFC = () => { return ( <SComponentContainer> <BrowserRouter> <Switch> <Route exact path={path.top}> <DefaultLayout> <Top /> </DefaultLayout> </Route> <Route path={path.help}> <DefaultLayout> <Help /> </DefaultLayout> </Route> <GuestRoute path={path.login}> <DefaultLayout> <Login /> </DefaultLayout> </GuestRoute> <GuestRoute path={path.register}> <DefaultLayout> <Register /> </DefaultLayout> </GuestRoute> <AuthRoute path={path.home}> <LoginedLayout> <Home /> </LoginedLayout> </AuthRoute> <AuthRoute path={path.quadrant}> <LoginedLayout> <Quadrant /> </LoginedLayout> </AuthRoute> <AuthRoute path={path.group}> <LoginedLayout> <Group /> </LoginedLayout> </AuthRoute> <AuthRoute path={path.edit}> <ActionLayout> <Edit /> </ActionLayout> </AuthRoute> <AuthRoute path={path.addgroup}> <ActionLayout> <AddGroup /> </ActionLayout> </AuthRoute> <AuthRoute path={path.addtask}> <ActionLayout> <AddTask /> </ActionLayout> </AuthRoute> <Route path="*"> <Redirect to={{ pathname: path.top }} /> </Route> </Switch> </BrowserRouter> </SComponentContainer> ); }; const SComponentContainer = styled.div` //色の指定 color: white; background-color: #423c3c; `;

AuthRoute.tsx

import React, { VFC } from "react"; import { Route, Redirect } from "react-router-dom"; import { useAuth } from "../hooks/useAuth"; import { useAuthContext } from "../providers/AuthProvider"; type propsType = { path: string; children: React.ReactNode; }; export const AuthRoute: VFC<propsType> = (props) => { const { isLogin } = useAuthContext(); useAuth(); const { path, children } = props; return ( <Route path={path} render={({ location }) => isLogin ? ( children ) : ( <Redirect to={{ pathname: "/login", state: { from: location }, }} /> ) } /> ); };

GuestRoute.tsx

React

1import React, { VFC } from "react"; 2import { Route, Redirect } from "react-router-dom"; 3import { useAuthContext } from "../providers/AuthProvider"; 4 5type propsType = { 6 path: string; 7 children: React.ReactNode; 8}; 9 10export const GuestRoute: VFC<propsType> = (props) => { 11 const { isLogin } = useAuthContext(); 12 const { path, children } = props; 13 return ( 14 <Route 15 path={path} 16 render={({ location }) => 17 isLogin ? ( 18 <Redirect 19 to={{ 20 pathname: "/home", 21 state: { from: location }, 22 }} 23 /> 24 ) : ( 25 children 26 ) 27 } 28 /> 29 ); 30}; 31

useAuth.tsx

import { useAuthContext } from "../providers/AuthProvider"; import axios from "axios"; export const useAuth = async () => { const { setIsLogin } = useAuthContext(); try { const res = await axios.get("/api/auth"); setIsLogin(res.data.isLogin); console.log("useAuth:ログイン情報を取得しisLoginセットしました"); } catch (error) { console.log("useAuth:ログイン情報が取得出来ませんでした"); } };

追記

AuthProvider.tsx

1import React, { createContext, useContext, useState, VFC } from "react"; 2 3const AuthContext = createContext( 4 {} as { 5 isLogin: boolean; 6 setIsLogin: React.Dispatch<React.SetStateAction<boolean>>; 7 } 8); 9 10type propsType = { 11 children: React.ReactElement; 12}; 13 14export const AuthProvider: VFC<propsType> = (props) => { 15 const { children } = props; 16 const [isLogin, setIsLogin] = useState<boolean>(false); 17 return ( 18 <AuthContext.Provider value={{ isLogin, setIsLogin }}> 19 {children} 20 </AuthContext.Provider> 21 ); 22}; 23 24export const useAuthContext = () => { 25 return useContext(AuthContext); 26}; 27

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/09/17 17:59

providers/AuthProvider のソースコードも追記いただけると対策が見えやすいかもしれません。
退会済みユーザー

退会済みユーザー

2021/09/18 03:54

おおきにです〜。回答しました。
hoshi-takanori

2021/09/26 21:27

リロードすると isLogin の初期状態は false で、ログインが必要な画面の場合、AuthRoute でいったん /login にリダイレクトされます。その後 /api/auth の結果が帰ってきて isLogin が true になると /home に飛ばされるのでしょう。 また、何回もログイン情報を取りに行っているのは、ログインが必要な画面に切り替わるたびに AuthRoute でログイン情報を取得しているからですね。
guest

回答2

0

自己解決

ログインしたかどうかの状態を追加することでなんとかなりました

投稿2021/10/07 09:56

it-tsumugi

総合スコア11

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

一案を回答します。

  • 解決策: isLoginをlocalStorageに永続化する。すなわちsetStateするときはlocalStorageにも保存し、読むときは、localStorageに保存してあればその値を優先的に使う。

  • 簡単な例 (で考え方を説明する記事): Persisting State in React Apps

  • 質問のコードへの実装例: 上記の記事からリンクされているuseLocalStorage を使って

diff

1- const [isLogin, setIsLogin] = useState<boolean>(false); 2+ const [isLogin, setIsLogin] = useLocalStorage('isLogin', false);

とする。(ただし、useLocalStorage のコードはJSなのでTSで使うと型のエラーや警告が出るかもしれないので、その場合は適宜対応)

  • useLocalStorage を使うのは一手段に過ぎないので、他のライブラリを探すか自分で書いてもよいかと思います。

投稿2021/09/18 03:54

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

it-tsumugi

2021/09/18 09:55

セッションで管理しているのでlocalStrageに保存したくないのです。XSSなどの対策も考えて
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問