🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Redux

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

Router

Routerは、異なるネットワーク同士を相互に接続するための通信機器。インターネットでのデータを自動的に振り分け、一つのインターネット回線を複数のコンピュータで使用することが可能です。DHCPによりIPアドレスを自動的に割振りすることもできます。

React.js

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

Q&A

解決済

1回答

7051閲覧

connected-react-routerを使ってurlを変えたのに表示されるコンポーネントが変わらない【React&Redux&TypeScript】

southernX

総合スコア5

Redux

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

Router

Routerは、異なるネットワーク同士を相互に接続するための通信機器。インターネットでのデータを自動的に振り分け、一つのインターネット回線を複数のコンピュータで使用することが可能です。DHCPによりIPアドレスを自動的に割振りすることもできます。

React.js

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

0グッド

0クリップ

投稿2019/10/09 17:31

編集2019/10/09 17:50

前提・実現したいこと

/signinページでボタンを押すと/countページに移動する

イメージ説明

イメージ説明
Countは今のところh1要素をレンダリングしているだけです。

発生している問題・エラーメッセージ

サインインページのログインボタンを押すと問題なく/countのurlに変わるのですが、表示されるコンポーネントが変わりません。しかしブラウザで再読み込みすればCountコンポーネントが表示されます

indexjs

1import * as React from 'react' 2import * as ReactDOM from 'react-dom' 3import { Provider } from "react-redux" 4import App from './App' 5import { store, history } from './modules/Store' 6 7 8ReactDOM.render( 9 <Provider store={store}> 10 <App history={history}/> 11 </Provider>, 12 document.getElementById('app') 13);

ルートディレクトリ下のindex.jsではAppコンポーネントをレンダリングするだけ。

App

1import * as React from 'react' 2import { History } from 'history' 3import { BrowserRouter, Route } from "react-router-dom"; 4import { ConnectedRouter } from 'connected-react-router' 5import SignIn from './containers/Signin' 6import Count from './containers/counter/Header' 7 8type AppProps = { 9 history: History; 10} 11 12const App = ({ history }: AppProps) => { 13 return( 14 <ConnectedRouter history={history}> 15 <BrowserRouter> 16 <Route exact path='/signin' component={SignIn} /> 17 <Route path='/count' component={Count} /> 18 </BrowserRouter> 19 </ConnectedRouter> 20 ) 21} 22 23 24export default App

Appコンポーネントはurlが/signinの時にSigninコンポーネントを、/countの時にCountコンポーネントをレンダリングします。

Signintsx

1import * as React from 'react'; 2import { connect } from 'react-redux' 3import { logInIfFetchUser } from '../modules/ActionCreater' 4import { AppState } from '../modules/Reducers' 5 6 7type SignInProps = { 8 logInIfFetchUser: any 9} 10class SignIn extends React.Component<SignInProps> { 11 render(){ 12 let email: any 13 let password: any 14 15 return( 16 <div> 17 <h1>サインイン</h1> 18 <form onSubmit={(e) => { 19 e.preventDefault() 20 console.log(`searching user with email: ${email.value}, password: ${password.value}`) 21 this.props.logInIfFetchUser(email.value, password.value) 22 }}> 23 <input type='text' ref={node => email = node}/> 24 <input type='password' ref={node => password = node}/> 25 <button type='submit'>ログイン</button> 26 </form> 27 </div> 28 ) 29 } 30} 31 32const mapStateToProps = (state: AppState) => { 33 34} 35 36export default connect(mapStateToProps,{ logInIfFetchUser })(SignIn) 37

SignInコンポーネントです。
onSubmitした時のアクションが以下の通りです。

ActionCreatorts

1import axios from 'axios' 2import { Action } from 'redux' 3import { ThunkAction } from "redux-thunk" 4import { push } from 'connected-react-router' 5import { LOGIN } from './ActionTypes' 6import { AppState } from './Reducers' 7 8export function logIn(userName: string) { 9 return { 10 type: 'LOGIN' as typeof LOGIN, 11 name: userName 12 } 13} 14 15 16export const logInIfFetchUser = ( 17 email: string, 18 password: string 19): ThunkAction<void, AppState, null, Action<string>> => async dispatch => { 20 axios.get(`http://localhost:8080/api/?email=${email}&password=${password}`) 21 .then((response) => { 22 dispatch(logIn(response.data[0].name)) 23 dispatch(push('/count')) 24 }) 25} 26

SignInで入力されたアドレスとパスワードと一致するユーザーをapiサーバーから返します。
その後、/countに移動します。
リクエストは成功し、ユーザーが返ってきたことは確認しました。

試したこと

connect()(SignIn)をさらにwithRouter()でラップしてみました。

connect()の引数を以下のように変えてみました。

export default connect(mapStateToProps, { logInIfFetchUser }, null, { pure: false })(SignIn)

その他のファイル(ReducerやStoreなど)

Reducerts

1import { Action, LOGIN } from './ActionTypes' 2import { Reducer, combineReducers } from 'redux' 3import { History } from 'history' 4import { connectRouter } from 'connected-react-router' 5 6type userReducerState = { 7 name: string 8} 9 10const initialState = { 11 name: '' 12} 13 14export const userReducer: Reducer<userReducerState, Action> = (state = initialState, action) => { 15 switch(action.type) { 16 case LOGIN: 17 return { 18 name: action.name 19 } 20 default: 21 return state; 22 } 23} 24 25export type userReducer = typeof userReducer 26 27export const rootReducer = (history: History) => combineReducers({ 28 router: connectRouter(history), 29 userReducer 30}) 31 32export type AppState = ReturnType<typeof rootReducer> 33

Storets

1import { createStore } from 'redux' 2import { applyMiddleware } from "redux"; 3import thunk from 'redux-thunk'; 4import { createBrowserHistory } from 'history' 5import { routerMiddleware } from 'connected-react-router' 6import { rootReducer } from "./Reducers"; 7 8export const history = createBrowserHistory() 9 10export const store = createStore( 11 rootReducer(history), 12 applyMiddleware( 13 routerMiddleware(history), 14 thunk 15 ) 16) 17

ActionCreator

1import { logIn } from './ActionCreater' 2 3export const LOGIN = 'LOGIN' 4export type Action = ReturnType<typeof logIn>

userReducerはまだ使っていません。後にユーザー名を取り出すつもりです。

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

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

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

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

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

guest

回答1

0

ベストアンサー

こちら、connected-react-routerのissueにも上がっている現象のようですね。
APIコールの後にpushをdispatchしても、URLは変わるがコンポーネントはそのままとのことです。
(#230)

パッと思いつく代替案としては、ログイン中か否かのStateを作って dispatch(push('/count')) の代わりにログイン中フラグをON→コンポーネント側の componentDidUpdate 等でログイン中フラグがOFF→ONになったら history.push('/count') 等で画面遷移させる、で実現できると思います。

もしくは、redux-sagaを使った例ですが丁寧なサンプルも落ちていたので併せて確認してみてください。
Reactサンプル:redux-sagaとreact-router v4でWebAPIの結果に応じて画面遷移させる。

投稿2019/10/10 01:05

guissy-k

総合スコア245

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

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

southernX

2019/10/10 16:53

history.pushのhistoryはcreateBrowserHistoryで作ったものですか?mapStateToPropsがうまくいかなかったのでアクション内で実行したところ依然としてコンポーネントが変わらないままです。
southernX

2019/10/11 13:27

propに変えてみましたが解決しませんでした・・・ 参考を拝見しましたが、おそらくこのpropsはconnect()でpushを渡したからコンポーネント内でできるのだと思います。
southernX

2019/10/11 14:59

Appコンポーネント内の<BrowserRouter></BrowserRouter>を<Switch>に変えると正しくページ遷移出来ました!回答ありがとうございました。
guissy-k

2019/10/15 03:32

解決できたようで良かったです。あまりお力になれずすみませんでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問