 
									この日は6つのファイルにコードを書き足しながら、ユーザーのログイン・ログアウト、そしてナビゲーションバーのリンクを完成させました。
①src/actions/auth.jsに./typesからのインポートとLogin user & Logoutのコードの書き足しを行う
import axios from "axios";
import { setAlert } from "./alert";
import {
  REGISTER_SUCCESS,
  REGISTER_FAIL,
  USER_LOADED,
  AUTH_ERROR,
  LOGIN_SUCCESS,
  LOGIN_FAIL,
  LOGOUT
} from "./types";
import setAuthToken from "../utils/setAuthToken";
// Load User
export const loadUser = () => async dispatch => {
  if (localStorage.token) {
    setAuthToken(localStorage.token);
  }
  try {
    const res = await axios.get("./api/auth");
    dispatch({
      type: USER_LOADED,
      payload: res.data
    });
  } catch (err) {
    dispatch({
      type: AUTH_ERROR
    });
  }
};
//Register User
export const register = ({ name, email, password }) => async dispatch => {
  const config = {
    headers: {
      "Content-Type": "application/json"
    }
  };
  const body = JSON.stringify({ name, email, password });
  try {
    const res = await axios.post("/api/users", body, config);
    dispatch({
      type: REGISTER_SUCCESS,
      payload: res.data
    });
    dispatch(loadUser());
  } catch (err) {
    const errors = err.response.data.errors;
    if (errors) {
      errors.forEach(error => dispatch(setAlert(error.msg, "danger")));
    }
    dispatch({
      type: REGISTER_FAIL
    });
  }
};
//Login User
export const login = (email, password) => async dispatch => {
  const config = {
    headers: {
      "Content-Type": "application/json"
    }
  };
  const body = JSON.stringify({ email, password });
  try {
    const res = await axios.post("/api/auth", body, config);
    dispatch({
      type: LOGIN_SUCCESS,
      payload: res.data
    });
    dispatch(loadUser());
  } catch (err) {
    const errors = err.response.data.errors;
    if (errors) {
      errors.forEach(error => dispatch(setAlert(error.msg, "danger")));
    }
    dispatch({
      type: LOGIN_FAIL
    });
  }
};
// Logout / Clear Profile
export const logout = () => dispatch => {
  dispatch({ type: LOGOUT });
};今回書き足しをしたのは、最初のimport {} from "./types"; 部分のLOGIN_SUCCESS, LOGIN_FAIL, LOGOUT 部分です。
そして、コメントアウトしているLogin User & Logoutの部分です。Login Userも部分については、まずはRegister Userからコードを持ってきて、必要ないものを消去したり少し書き換えるだけ、という方法をとりました。
②src/actions/types.js のコードを書き足す。
先程の、src/actions/auth.jsの最初の部分でimport {} from "./types"; とコードを書いた、ということはtypes.jsも書き足しが必要ですよね。というわけで、こちらにもログイン・ログアウト情報などを書き加えました。
export const SET_ALERT = "SET_ALERT";
export const REMOVE_ALERT = "REMOVE_ALERT";
export const REGISTER_SUCCESS = "REGISTER_SUCCESS";
export const REGISTER_FAIL = "REGISTER_FAIL";
export const USER_LOADED = "USER_LOADED";
export const AUTH_ERROR = "AUTH_ERROR";
export const LOGIN_SUCCESS = "LOGIN_SUCCESS";
export const LOGIN_FAIL = "LOGIN_FAIL";
export const LOGOUT = "LOGOUT";③src/reducers/auth.jsにも、LOGIN_SUCCESS, LOGIN_FAIL, LOGOUTのコードを書き足す
こちらはシンプルで、import {} from "..actions/types"; の部分へのコード書き足しと、switchのcaseの部分への書き足しのみとなりました。
import {
  REGISTER_SUCCESS,
  REGISTER_FAIL,
  USER_LOADED,
  AUTH_ERROR,
  LOGIN_SUCCESS,
  LOGIN_FAIL,
  LOGOUT
} from "../actions/types";
const initialState = {
  token: localStorage.getItem("token"),
  isAuthenticated: null,
  loading: true,
  user: null
};
export default function(state = initialState, action) {
  const { type, payload } = action;
  switch (type) {
    case USER_LOADED:
      return {
        ...state,
        isAuthenticated: true,
        loading: false,
        user: payload
      };
    case REGISTER_SUCCESS:
    case LOGIN_SUCCESS:
      localStorage.setItem("token", payload.token);
      return {
        ...state,
        ...payload,
        isAuthenticated: true,
        loading: false
      };
    case REGISTER_FAIL:
    case AUTH_ERROR:
    case LOGIN_FAIL:
    case LOGOUT:
      localStorage.removeItem("token");
      return {
        ...state,
        token: null,
        isAuthenticated: false,
        loading: false
      };
    default:
      return state;
  }
}
④ component/auth/Login.jsへのコード書き加え(Login.jsの完成)
Login.jsへは沢山コードを書き加えました。最初のimport部分には、Redirect, connect, PropTypes, loginを書き加え、それに合わせて、最後11行、Login.Proptypesから始まるコードを書き加えています。点と点だったものがやっと繋ぎ合わさり、Login.jsファイルは完成となりました!
import React, { Fragment, useState } from "react";
import { Link, Redirect } from "react-router-dom";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import { login } from "../../actions/auth";
const Login = ({ login, isAuthenticated }) => {
  const [formData, setFormData] = useState({
    email: "",
    password: ""
  });
  const { email, password } = formData;
  const onChange = e =>
    setFormData({ ...formData, [e.target.name]: e.target.value });
  const onSubmit = async e => {
    e.preventDefault();
    login(email, password);
  };
  if (isAuthenticated) {
    return ;
  }
  return (
//fragment内のコードがブログ上では上手く表示されないため割愛。(Sign in, Login, Sign up部分の表示をするためのコード) 
  );
};
Login.propTypes = {
  login: PropTypes.func.isRequired,
  isAuthenticated: PropTypes.bool
};
const mapStateToProps = state => ({
  isAuthenticated: state.auth.isAuthenticated
});
export default connect(
  mapStateToProps,
  { login }
)(Login);
 最初は/dashboardへのリダイレクトが上手くいかず少し焦ったのですが、もう一度書き直しをすることで上手くいきました。
⑤components/auth/Register.jsを完成させる
Register.jsもLogin.jsと同様、import部分に Redirectを書き加えています。
また、const RegisterにはisAuthenticatedを書き加え、'/dashboard'にリダイレクトするようにしました。
最後の方にはconst mapStateToPropsを作成しています。
import React, { Fragment, useState } from "react";
import { connect } from "react-redux";
import { Link, Redirect } from "react-router-dom";
import { setAlert } from "../../actions/alert";
import { register } from "../../actions/auth";
import PropTypes from "prop-types";
const Register = ({ setAlert, register, isAuthenticated }) => {
  const [formData, setFormData] = useState({
    name: "",
    email: "",
    password: "",
    password2: ""
  });
  const { name, email, password, password2 } = formData;
  const onChange = e =>
    setFormData({ ...formData, [e.target.name]: e.target.value });
  const onSubmit = async e => {
    e.preventDefault();
    if (password !== password2) {
      setAlert("Passwords do not match", "danger");
    } else {
      register({ name, email, password });
    }
  };
  if (isAuthenticated) {
    return ;//Redirectで/dashboardへ。
  }
  return (
   //Fragment内のコードがブログ上で上手く表示されないため割愛。Sign up, Create Your Account, フォームのonSubmit等のコード。  ⑥src/components/layout/Navbar.js ナビゲーションバーにimportとログアウトコード書き加え
Navbar.jsは元々ファイルを作成した時にはシンプルにimport Reactと{Link}周りのコードをを書いていたのみだったのですが、{connect} , PropTypes, {logout}を書き加えました。
また、const Navbarなどでログアウトもできるようにコードを書き加えました。最終的にこのファイルでもpropTYpes mapStateToProps等を利用するようにしています。
import React, { Fragment } from "react";
import { Link } from "react-router-dom";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import { logout } from "../../actions/auth";
const Navbar = ({ auth: { isAuthenticated, loading }, logout }) => {
  const authLinks = (
  //onClickでログアウト(割愛)
); const guestLinks = (
//Developers, Register, Loginへのリンク(割愛)
); return (); }; Navbar.propTypes = { logout: PropTypes.func.isRequired, auth: PropTypes.object.isRequired }; const mapStateToProps = state => ({ auth: state.auth }); export default connect( mapStateToProps, { logout } )(Navbar);
本日の学習の感想(99日目)
ファイルの数が増えてきたのでtreeを書いて全体像を把握しました。割とシンプルなアプリケーションになる予定なのですが、それでもコードは沢山書かなければならないのだなぁという印象です。繰り返しに近いことも多いので慣れてきた部分と、まだはっきりわかっていない部分があるので、復習しながら学習を進めたいです。
次回で、まずは目標としていた100日目に到達します!できなかったことより、できたことを数えていくのが(プログラミングに限らずですが)学習を継続していくコツだと思いました。
現在使用している教材と学習時間:本日の学習時間2.5時間
Udemy:MERN Stack Front To Back: Full Stack React, Redux & Node.js by Brad Traversy
★Section8:React User Authentication
-Lec 42 User Login
-Lec 43 Logout & Navbar Links (ここまで完了。Section8終了)
進捗状況:59%
学習時間2.5時間
~本日は休みにしている教材~
Udemy:The Complete Web Developer: Zero to Mastery by Andrei Neagoie
進捗状況: 92%
★参考にした本★
「React.js & Next.js超入門」掌田津耶乃 (秀和システム)
Section4-1: Reduxを使ってみよう
★参照記事★
Quiita参照記事⇒[axios] axios の導入と簡単な使い方
 
                     
                     
                     
                     
                         
                         
                         
                         
                         
                         
                        