AsrulDev

AsrulDev

Hari 21: Deploy Netlify

Hari 21: Deploy Netlify

30 Hari Javascript

Subscribe to my newsletter and never miss my upcoming articles

Persiapan Deploy

Setelah latihan kesegaran otak mari kita lanjut materi kembali, kita akan melakukan deploy ke https://www.netlify.com (tau kenapa?, iya benar GRATISSSSSS).

Sedikit kita lengkapi, untuk halaman login, silahkan buat file page/Login.js yang isinya seperti berikut.

import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { loginUser } from "../actions/user.action";

const Login = (props) => {
  const dispatch = useDispatch();
  const [user, updateUser] = useState({});

  const submitForm = (e) => {
    e.preventDefault();
    dispatch(loginUser(user));
  };

  return (
    <div className="page">
      <h1 className="page-title">Login 30 Hari Js</h1>

      <form className="login" onSubmit={(e) => submitForm(e)}>
        <label>Email</label>
        <input
          type="email"
          autoComplete={"false"}
          placeholder="email"
          onChange={(e) => {
            updateUser({ ...user, email: e.target.value });
          }}
        />

        <label>Password</label>
        <input
          type="password"
          autoComplete={"false"}
          placeholder="rahasia"
          onChange={(e) => {
            updateUser({ ...user, password: e.target.value });
          }}
        />

        <button type="submit" onClick={(e) => submitForm(e)}>
          Login
        </button>
      </form>
    </div>
  );
};

export default Login;

Ubah sedikit file user.action.js menjadi seperti berikut.

import axios from "axios";

const baseUrl = `https://warm-refuge-26108.herokuapp.com`;

export const getUsers = () => {
  return async (dispatch) => {
    dispatch({
      type: "GET_USER_REQUEST",
    });
    try {
      const result = await axios.get(baseUrl + `/users`);
      dispatch({
        type: "GET_USER_DONE",
        payload: result.data,
      });
    } catch (error) {
      dispatch({
        type: "GET_USER_ERROR",
      });
    }
  };
};

export const createUser = (data) => {
  return async (dispatch) => {
    try {
      const result = await axios.post(baseUrl + `/users`, data);
      return result;
    } catch (error) {
      dispatch({
        type: "GET_USER_ERROR",
      });
    }
  };
};

export const loginUser = (data) => {
  return async (dispatch) => {
    try {
      const result = await axios.post(baseUrl + `/users/login`, data);
      window.localStorage.setItem("token", result.data.token);

      if (result.data.token) {
        window.location.href = "/profile";
      }
      return result;
    } catch (error) {
      dispatch({
        type: "GET_USER_ERROR",
      });
    }
  };
};

export const profileUser = () => {
  return async (dispatch) => {
    dispatch({
      type: "GET_USER_REQUEST",
    });
    try {
      const result = await axios.get(baseUrl + `/users/profile`, {
        headers: { token: window.localStorage.getItem("token") },
      });
      dispatch({
        type: "GET_USER_DETAIL_DONE",
        payload: result.data,
      });
    } catch (error) {
      dispatch({
        type: "GET_USER_ERROR",
      });
    }
  };
};

Ubah juga file user.reducer.js, dan menjadi seperti berikut.

const initialState = {
  data: [],
  isError: false,
  isLoading: false,
  detail: null,
};

export default (state = initialState, action) => {
  switch (action.type) {
    case "GET_USER_REQUEST":
      return {
        ...state,
        isError: false,
        isLoading: true,
      };
    case "GET_USER_DONE":
      return {
        ...state,
        data: action.payload,
        isError: false,
        isLoading: false,
      };
    case "GET_USER_DETAIL_DONE":
      return {
        ...state,
        detail: action.payload,
        isError: false,
        isLoading: false,
      };
    case "GET_USER_ERROR":
      return {
        ...state,
        isError: true,
        isLoading: false,
      };
    default:
      return state;
  }
};

Tambahkan file page/Profile.js, yang isinya seperti berikut.

import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { profileUser } from "../actions/user.action";

const Profile = (props) => {
  const dispatch = useDispatch();
  const usersData = useSelector((state) => state.users);

  useEffect(() => {
    dispatch(profileUser());
  }, []);

  if (usersData.detail === null) {
    return <h1>Loading...</h1>;
  }

  return (
    <div className="page">
      <h1 className="page-title">My Profile</h1>

      <div className="profile">
        <div className="avatar">
          <img src={usersData.detail.picture} />
        </div>
        <div className="profile-detail">
          <div>
            <h3> {usersData.detail.name} </h3>
            <hr />
            <span> {usersData.detail.label} </span>

            <p style={{ marginTop: "3rem" }}> {usersData.detail.phone} </p>
            <p style={{ marginTop: "1rem" }}> {usersData.detail.email} </p>
            <p style={{ marginTop: "1rem" }}> {usersData.detail.website} </p>

            <p style={{ marginTop: "3rem" }}>
              Summary: {usersData.detail.summary}{" "}
            </p>
          </div>
        </div>
      </div>
    </div>
  );
};

export default Profile;

Ubah file RouterApp.js untuk mengubah menu sehingga kode menjadi seperti berikut.

import React, { Component, Fragment } from "react";
import { BrowserRouter, Switch, Route, Link } from "react-router-dom";

import Home from "./pages/Home";
import About from "./pages/About";
import Profile from "./pages/Profile";
import Register from "./pages/Register";
import Login from "./pages/Login";

class RouterApp extends Component {
  state = {
    token: null,
  };

  componentDidMount() {
    const token = window.localStorage.getItem("token");
    this.setState({ token });
  }

  render() {
    return (
      <BrowserRouter>
        <Fragment>
          <nav>
            <li>
              {" "}
              <Link to="/"> Home </Link>{" "}
            </li>
            <li>
              {" "}
              <Link to="/about"> About </Link>{" "}
            </li>
            {this.state.token === null && (
              <>
                <li>
                  {" "}
                  <Link to="/register"> Register </Link>{" "}
                </li>
                <li>
                  {" "}
                  <Link to="/login"> Login </Link>{" "}
                </li>
              </>
            )}
            {this.state.token !== null && (
              <>
                <li>
                  {" "}
                  <Link to="/profile"> Profile </Link>{" "}
                </li>
                <li>
                  {" "}
                  <a
                    href="#"
                    onClick={() => {
                      window.localStorage.removeItem("token");
                      window.location.href = "/";
                    }}
                  >
                    {" "}
                    Logout{" "}
                  </a>{" "}
                </li>
              </>
            )}
          </nav>

          <main>
            <Switch>
              <Route path="/" exact component={Home} />
              <Route path="/about" exact component={About} />
              {this.state.token !== null && (
                <Route path="/profile" exact component={Profile} />
              )}

              {this.state.token === null && (
                <>
                  <Route path="/register" exact component={Register} />
                  <Route path="/login" exact component={Login} />
                </>
              )}
            </Switch>
          </main>
        </Fragment>
      </BrowserRouter>
    );
  }
}

export default RouterApp;

Agar terlihat elegan tambahkan css pada file App.css yang isinya seperti berikut.

* {
  margin: 0;
  padding: 0;
  text-decoration: none;
  list-style: none;
}

body {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  -ms-flex-direction: column;
  flex-direction: column;
  min-height: 100vh;
}

body nav {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
  -ms-flex-direction: row;
  flex-direction: row;
  -webkit-box-pack: end;
  -ms-flex-pack: end;
  justify-content: flex-end;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
  background: green;
  width: 100%;
  height: 40px;
}

body nav li {
  margin-right: 2rem;
}

body nav li a {
  color: white;
}

body nav li a:hover {
  color: yellow;
}

body main {
  padding: 3rem;
  color: gray;
}

.page {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  -ms-flex-direction: column;
  flex-direction: column;
}

.page .page-title {
  color: black;
  text-align: center;
  margin-bottom: 1rem;
}

.page .users {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: start;
  -ms-flex-pack: start;
  justify-content: flex-start;
  -ms-flex-wrap: wrap;
  flex-wrap: wrap;
}

.page .users .user {
  width: calc(calc(100% / 4) - 1rem);
  border: 1px green solid;
  margin-right: 1rem;
  margin-bottom: 1rem;
}

.page .users .user:nth-child(4n) {
  margin-right: 0;
}

.page .users .user .user-img-container img {
  width: 100%;
  -o-object-fit: cover;
  object-fit: cover;
}

.page .users .user .user-detail h3 {
  text-align: center;
  margin-top: 0.5rem;
  margin-bottom: 0.5rem;
}

.page .register,
.page .login {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  -ms-flex-direction: column;
  flex-direction: column;
  min-width: 80%;
  margin: auto;
}

.page .register input,
.page .register textarea,
.page .login input,
.page .login textarea {
  margin-bottom: 1rem;
  padding: 0.5rem;
  outline: none;
}

.page .register input:focus,
.page .register textarea:focus,
.page .login input:focus,
.page .login textarea:focus {
  border: 1px solid green;
}

.page .register button,
.page .login button {
  color: #ffffff;
  background: green;
  padding: 0.5rem;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.page .register button:hover,
.page .login button:hover {
  background: #ffffff;
  color: green;
  border: 1px solid green;
}

.page .profile {
  width: 800px;
  min-width: 800px;
  max-width: 800px;
  padding: 2rem;
  border: 1px dotted black;
  margin: auto;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
}

.page .profile .avatar {
  margin-right: 1rem;
}

.page .profile .avatar img {
  width: 200px;
  border-radius: 50%;
  border: 1px solid red;
}

Source cek disini

Deploy

Pertama sekali, silahkan login ke netlify atau jika belum memiliki akun silahkan daftar terlebih dahulu.

https://raw.githubusercontent.com/AsrulLove/img-db/master/netlify.png

Kemudian pada proyek react build untuk di upload ke hosting dengan perintah berikut.

npm run build

Maka akan menghasilkan file compress dari proyek react tersebut.

https://raw.githubusercontent.com/AsrulLove/img-db/master/npm-run-build.png

Selanjutnya folder build drag ke netlify seperti berikut.

https://raw.githubusercontent.com/AsrulLove/img-db/master/dnd-netlify.png

Setelah di drag, maka netlify memberikan url yang dapat kita gunakan sebagai alamat web kita.

https://raw.githubusercontent.com/AsrulLove/img-db/master/url-netlify.png

Jika ingin mengubah url, netlify menyediakannya melalui custom domain.

https://raw.githubusercontent.com/AsrulLove/img-db/master/custom-url.png

 
Share this
Proudly part of