こんにちは、KOUKIです。Reactでアプリケーションを開発しています。
ナビゲーションを実装します。
尚、「React, NextJS and Golang: A Rapid Guide – Advanced」コースを参考にしています。解釈は私が勝手に付けているので、本物をみたい場合は受講をお勧めします!
<目次>
前回
ナビゲーション
BootstrapのHeadersを参考に、ナビゲーションを実装しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// components/Nav.tsx const Nav = () => { let menu menu = ( <div className="col-md-3 text-end"> <button type="button" className="btn btn-outline-primary me-2">Login</button> <button type="button" className="btn btn-primary">Sign-up</button> </div> ) return ( <div className="container"> <header className="d-flex flex-wrap align-items-center justify-content-center justify-content-md-between py-3 mb-4 border-bottom"> <ul className="nav col-12 col-md-auto mb-2 justify-content-center mb-md-0"> <li><a href="#" className="nav-link px-2 link-secondary">Frontend</a></li> <li><a href="#" className="nav-link px-2 link-dark">Backend</a></li> </ul> </header> </div> ) } export default Nav |
「docker-compose up」でコンテナを立ち上げ、「http://localhost:4000/」にアクセスします。

ナビゲーションを導入できました。
Redux Storeへ接続
ナビゲーションもRedux Storeへ接続します。
※Reduxは、前回導入しました
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// components/Nav.tsx import { connect } from 'react-redux' import { User } from '../models/user' // propsをつける const Nav = (props: {user: User}) => { ... } // Redux StoreからUser情報を取得する export default connect( (state: {user: User}) => ({ user: state.user }) )(Nav) |
ログインするとユーザー情報がRedux Storeに格納されるので、そこから取得します。
ヘッダーの動的変更
Redux Storeから取得したユーザー情報を使って、ヘッダーの切り替えを行います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
// components/Nav.tsx import { useState } from 'react' import { connect } from 'react-redux' import { User } from '../models/user' import { Link, Redirect } from 'react-router-dom' import axios from 'axios' const Nav = (props: {user: User}) => { const [redirect, setRedirect] = useState(false) const logout = async () => { await axios.post('logout') setRedirect(true) } if (redirect) { return <Redirect to={'/login'} /> } let menu if (props.user?.id) { menu = ( <div className="col-md-3 text-end"> <Link to={'/profile'} href="#" className="btn btn-primary"> {props.user.first_name} {props.user.last_name} </Link> <a href="#" className="btn btn-outline-primary me-2" onClick={logout} > logout </a> </div> ) } else { menu = ( <div className="col-md-3 text-end"> <Link to={'/login'} className="btn btn-outline-primary me-2">Login</Link> <Link to={'/register'} className="btn btn-primary">Sign-up</Link> </div> ) } ... } |
以下の条件で、ナビゲーションを変えました。
<ログインしていない時>
Login/Sign-upを表示
<ログインしている時>
ユーザー名/Logoutを表示
ただし、現状だとログインしていない時のナビゲーションを出すことが不可能なので、LayoutページからRedirect処理を削除します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
// components/Layout.tsx ... const Layout = (props: any) => { const userURL = 'user' // const [redirect, setRedirect] = useState(false) useEffect(() => { ( async () => { try { const { data } = await axios.get(userURL) props.setUser(data) } catch(e) { console.log(e) // setRedirect(true) } } )() }, []) // if (redirect) { // return <Redirect to={'/login'} /> // } return ( ... ) } ... |
コメントアウトした部分を消してください。
検証
ナビゲーションの検証をしましょう。
大丈夫そうですね。なお、Profileページは作成していないので、空欄でOKです。
次回
次回は、ヘッダーのコンポーネントを実装しましょう。
Reactまとめ
参考書籍
ソースコード
Nav.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
// components/Nav.tsx import { useState } from 'react' import { connect } from 'react-redux' import { User } from '../models/user' import { Link, Redirect } from 'react-router-dom' import axios from 'axios' const Nav = (props: {user: User}) => { const [redirect, setRedirect] = useState(false) const logout = async () => { await axios.post('logout') setRedirect(true) } if (redirect) { return <Redirect to={'/login'} /> } let menu if (props.user?.id) { menu = ( <div className="col-md-3 text-end"> <Link to={'/profile'} href="#" className="btn btn-primary"> {props.user.first_name} {props.user.last_name} </Link> <a href="#" className="btn btn-outline-primary me-2" onClick={logout} > logout </a> </div> ) } else { menu = ( <div className="col-md-3 text-end"> <Link to={'/login'} className="btn btn-outline-primary me-2">Login</Link> <Link to={'/register'} className="btn btn-primary">Sign-up</Link> </div> ) } return ( <div className="container"> <header className="d-flex flex-wrap align-items-center justify-content-center justify-content-md-between py-3 mb-4 border-bottom"> <ul className="nav col-12 col-md-auto mb-2 justify-content-center mb-md-0"> <li><a href="#" className="nav-link px-2 link-secondary">Frontend</a></li> <li><a href="#" className="nav-link px-2 link-dark">Backend</a></li> </ul> {menu} </header> </div> ) } export default connect( (state: {user: User}) => ({ user: state.user }) )(Nav) |
Layout.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
// components/Layout.tsx import { Dispatch, useEffect, useState } from 'react' import { connect } from 'react-redux' import { User } from '../models/user' import { setUserAction } from '../redux/actions/setUserAction' import Nav from './Nav' import Header from './Header' import axios from 'axios' const Layout = (props: any) => { const userURL = 'user' useEffect(() => { ( async () => { try { const { data } = await axios.get(userURL) props.setUser(data) } catch(e) { console.log(e) } } )() }, []) return ( <div> <Nav /> <main> <Header /> <div className="album py-5 bg-light"> <div className="container"> {props.children} </div> </div> </main> </div> ) } // State const mapStateToProps = (state: {user: User}) => ({ user: state.user }) // Dispatch const mapDispatchToProps = (dispatch: Dispatch<any>) => ({ // setUser(Action)->dispatch setUser: (user: User) => dispatch(setUserAction(user)) }) // LayoutコンポーネントをRedux Storeに登録 export default connect(mapStateToProps, mapDispatchToProps)(Layout) |
コメントを残す
コメントを投稿するにはログインしてください。