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

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

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

Reduxは、JavaScriptアプリケーションの状態を管理するためのオープンソースライブラリです。ReactやAngularで一般的にユーザーインターフェイスの構築に利用されます。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

React.js

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

解決済

react-reduxにて、storeの値を取得してからactionをdispatchする方法

Toshiyuki023
Toshiyuki023

総合スコア3

Redux

Reduxは、JavaScriptアプリケーションの状態を管理するためのオープンソースライブラリです。ReactやAngularで一般的にユーザーインターフェイスの構築に利用されます。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

React.js

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

2回答

0リアクション

0クリップ

2925閲覧

投稿2020/09/11 00:12

編集2020/09/11 00:18

環境

axios: "0.20.0",
react: "16.13.1",
react-dom: "16.13.1",
react-redux: "7.2.1",
redux-thnx : "2.3.0"

コード

actions

import * as actionTypes from './actionType'; import axios from 'axios'; import { useSelector } from 'react-redux'; import { store } from '../../index'; export const authStart = () => { return { type: actionTypes.AUTH_START, }; }; export const authSuccess = (token,uid) => { return { type: actionTypes.AUTH_SUCCESS, token: token, uid:uid }; }; export const setUid = (uid) => { return { type: actionTypes.SET_UID, uid: uid, }; }; export const authFail = (error) => { return { type: actionTypes.AUTH_FAIL, error: error, }; }; export const logout = () => { localStorage.removeItem('token'); localStorage.removeItem('expirationDate'); axios .post('http://localhost:8000/rest-auth/logout/') .then((res) => { console.log(res.json()); }) .catch((err) => { console.log(err); }); return { type: actionTypes.AUTH_LOGOUT, }; }; // ======================== ======================== ======================== ======================== // 以下redux-thunx用のasync action creator ========= ============ =============- =========== export const checkAuthTimeout = (expirationTime) => { return (dispatch) => { setTimeout(() => { dispatch(logout()); }, expirationTime * 1000); }; }; export const getUserId = (username) => { return (dispatch) => { axios.get('http://localhost:8000/api/user').then((res) => { const users = res.data; const currentUser = users.filter((user) => user.username === username)[0]; const uid = currentUser.id; dispatch(authSuccess(localStorage.getItem('token'), uid)); }); }; }; export const authLogin = (username, password) => { return (dispatch) => { dispatch(authStart()); axios .post('http://localhost:8000/rest-auth/login/', { username: username, password: password, }) .then((res) => { const token = res.data.key; const expirationDate = new Date(new Date().getTime() + 3600 * 1000); localStorage.setItem('token', token); localStorage.setItem('expirationDate', expirationDate); dispatch(getUserId(username)); dispatch(checkAuthTimeout(3600)); }) .catch((err) => { dispatch(authFail(err)); }); }; }; export const authSignup = (username, email, password) => { return (dispatch) => { dispatch(authStart()); axios .post('http://localhost:8000/rest-auth/registration/', { username: username, email: email, password: password, }) .then((res) => { const token = res.data.key; const expirationDate = new Date(new Date().getTime() + 3600 * 1000); localStorage.setItem('token', token); localStorage.setItem('expirationDate', expirationDate); // getUserId内でauthSuccessが実行され、auth_SUCCESSへuid, tokenがセット dispatch(getUserId(username)); dispatch(checkAuthTimeout(3600)); }) .catch((err) => { dispatch(authFail(err)); }); }; }; export const authCheckState = () => { return async(dispatch) => { const token = localStorage.getItem('token'); if (token === undefined) { dispatch(logout()); } else { const expirationDate = new Date(localStorage.getItem('expirationDate')); if (expirationDate <= new Date()) { dispatch(logout()); } else { // //uidを取得してからauthSuccessを実行させたいです。 const uid = await store.getState().uid; dispatch(authSuccess(token, uid)); console.log("uid is " + uid + " and token is " + token) dispatch(checkAuthTimeout((expirationDate.getTime() - new Date().getTime()) / 1000)); } } }; };

reducer

import * as actionTypes from './actionType'; import { updateObject } from '../utility'; const initialState = { token: null, error: null, loading: false, uid: null, }; const authStart = (state, action) => { return updateObject(state, { error: null, loading: true, }); }; const authSuccess = (state, action) => { // updateObjectによりstateの更新をfunction化 return updateObject(state, { token: action.token, error: null, loading: false, uid : action.uid }); }; const authFail = (state, action) => { return updateObject(state, { error: action.error, loading: false, }); }; const authLogout = (state, action) => { return updateObject(state, { token: null, uid: null, }); }; const setUid = (state, action) => { return updateObject(state, { uid: action.uid, }); }; export const reducer = (state = initialState, action) => { switch (action.type) { case actionTypes.AUTH_START: return authStart(state, action); case actionTypes.AUTH_SUCCESS: return authSuccess(state, action); case actionTypes.AUTH_FAIL: return authFail(state, action); case actionTypes.AUTH_LOGOUT: return authLogout(state, action); default: return state; } }; export default reducer;

App

import React, { Component } from 'react'; import { BrowserRouter as Router, Route } from 'react-router-dom'; import { connect } from 'react-redux'; import * as actions from './reducks/auth/actions'; import { Link } from 'react-router-dom'; import Register from './containers/Pages/Register'; import Login from './containers/Pages/Login'; import Add_Want_Item from './containers/Pages/Add_Want_Item'; class App extends Component { componentDidMount() { // tokenがローカルに存在してるかの確認、expirationdateの期限確認 this.props.onTryAutoSignup(); } render() { return ( <Router> {/* Route内のRoutePassはpropsを渡す役割を果たす */} <Route exact path="/registration" render={(routeProps) => <Register {...routeProps} {...this.props} />} /> <Route exact path="/login" render={(routeProps) => <Login {...routeProps} {...this.props} />} /> <Route exact path="/user/want/add" component={Add_Want_Item} /> </Router> ); } } const mapStateToProps = (state) => { return { isAuthenticated: state.token !== null, }; }; const mapDispatchToProps = (dispatch) => { return { onTryAutoSignup: () => dispatch(actions.authCheckState()), }; }; export default connect(mapStateToProps, mapDispatchToProps)(App);

やりたいこと

actions内で、ストアからのuid取得を待ち、uidを取得した後にuidを引数とするauthSuccessをdispatchしたいです。

問題点

actionの一つauthCheckState内におけるdispatch(authSuccess(token, uid))uidが取得されないまま処理が進んでしまうことで、uidnullになり、結果、actionauthSuccessによってstateuid : nullに書き換えられてしまうことです。

最終的に私が行いたいのは、uidをログインしているユーザーのものにすることです。
ログイン時、または、新規登録時にuidを更新することには成功しているのですが(actionauthSignup, authLogin参照)、画面遷移を行うとuidnullに上書きされてしまいます。
原因は、App.jsx内でauthCheckStateがdispatchされた時に、authSuccessの引数の一つであるuidが、ログイン済みユーザーのIDを持たないままdispatchされたことにより、stateuidnullへ変わってしまうために起きていると私は考察しています。

解決法として、authCheckState内でstoreからuidを取得してきて、それをauthSuccessの引数に入れるということを思いつき、async/awaitで実装をしてみました。しかし、依然としてuidnullのままだったため、store.getState()の処理の完了が待たれずにauthSuccessが実行されている様に思われます。

どの様にすれば、uidauthSuccess間の非同期を制御し、uidauthSuccessに入れることができるかを教えていただきたいです。

分かりづらい説明となってしまい、大変申し訳ありません。
ご回答いただければ幸いです。
よろしくお願いいたします。

以下のような質問にはリアクションをつけましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

リアクションが多い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
86.12%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Redux

Reduxは、JavaScriptアプリケーションの状態を管理するためのオープンソースライブラリです。ReactやAngularで一般的にユーザーインターフェイスの構築に利用されます。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

React.js

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