誰もが少なくとも一度は取り組んだことがあると思う非常に有名な問題があります。ページが更新されても、反応アプリにログインしているユーザーを保持したい。これを行う方法に関する関連する質問と記事をすべて読みましたが、残念ながらどこにも行きませんでした。私の ProtectedComponent には、次のコードがあります。
const ProtectedRoute = ({ notLoggedInPath }) => {
const isLoggedIn = useSelector((state) => state.auth.isLoggedIn);
return (
<Fragment>
{isLoggedIn && <RecorderPage />}
{!isLoggedIn && <Redirect to={notLoggedInPath} />}
</Fragment>
);
};
ご覧のとおり、認証レデューサーの initialState に isLoggedIn という変数を実装しました。この変数が true の場合、保護されたルートにアクセスできます。それ以外の場合はアクセスできません。
サインイン コンポーネントで、受信したトークンを API から localStorage に保存します。これで完全に完了です。しかし、私の主な質問は、ユーザーがサインインしてから保護されたルートに移動すると、ページを更新することで initialState(isLoggedIn) が消えて false に変わり、ユーザーがログアウトすることです。これは、ReactJS の文化ではまったく自然なことです。しかし、アプリの起動時に、以前に受信したトークンの認証を探し、まだ期限切れになっていない場合は、ユーザーをアプリが更新されたページに移動する方法を実装するにはどうすればよいですか。これは膨大な数のウェブサイトで行われているので、私はそれが可能であることを知っています. でも方法がわからない?
私のサインインコンポーネント:
const SignInForm = () => {
const dispatch = useDispatch();
const history = useHistory();
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = () => {
axios({
method: 'post',
url: 'someurl/api/token/',
data: {
username: username,
password: password,
},
})
.then((res) => {
const token = res.data.access;
localStorage.setItem('token', token);
dispatch(updateUserInStore(token, username));
dispatch(makeUserLoggedIn());
history.push('/recorder');
})
.catch((err) => {
console.log(err);
console.log(err.response);
});
};
return (
<some jsx/>
)
マザーレベルのコンポーネント App でフック useEffect も使用したことは言及する価値があります。つまり、アプリが useEffect でコールバックを起動すると、localStorage トークンが承認されているかどうかがチェックされますが、js の非同期の性質と axios 要求のために、この axios 要求の応答が受信される前に initialState が設定されるため、これは解決策ではありません。 .
私のアプリのコンポーネント:
const App = () => {
const dispatch = useDispatch();
const history = useHistory();
const tokenLocalStored = localStorage.getItem('token');
const checkIfUserCanBeLoggedIn = () => {
const token = localStorage.getItem('token');
axios({
method: 'get',
url: 'some-url/api/sentence',
headers: {
Authorization: `Bearer ${token}`,
},
})
.then((res) => {
dispatch(makeUserLoggedIn());
})
.catch((err) => {
console.log(err);
console.log(err.response);
return false;
});
};
useEffect(() => {
checkIfUserCanBeLoggedIn();
});
return (
<Some JSX>
)