Search by

    Terakhir diperbaharui: Oct 24, 2020

    Enhancement

    Meskipun aplikasi DinoTes sekarang sudah bisa digunakan namun masih ada beberapa hal yang bisa dilakukan untuk meningkatkan kualitas (enhance) baik dari sisi aplikasi atau user experience (UX) dalam menggunakan aplikasi DinoTes ini, diantaranya:

    • Refactoring, membuat reusable function
    • Update tampilan dari styled component Button
    • Menambah note preview pada component NotesList
    • Menampilkan pesan ketika note berhasil ditambahkan
    • Membuat Git Repository

    Membuat Reusable Function

    Jika diamati code berikut muncul di beberapa tempat:

    1...
    2
    3const existing = localStorage.getItem('notes');
    4
    5const notes = existing ? JSON.parse(existing) : [];
    6
    7...

    Kita bisa membuat sebuah reusable function dari code di atas.

    Yang dimaksud reusable function disini adalah function yang bersifat shared seperti shared components.

    Step by step

    1. Buat file baru bernama getLocalStorageData.js di dalam folder src/utils.

    Struktur Folder

    1dinotes-app
    2 |--node_modules
    3 |--public
    4 |--src
    5 |--assets
    6 |--components
    7 |--layouts
    8 |--pages
    9 |--utils
    10 |--getLocalStorageData.js
    11 ...
    1. Salin code berikut ke src/utils/getLocalStorageData.js.
    1const getLocalStorageData = (itemName) => {
    2 const existing = localStorage.getItem(itemName);
    3
    4 return existing ? JSON.parse(existing) : [];
    5};
    6
    7export default getLocalStorageData;
    1. Update src/components/NotesList.js.
    1...
    2
    3import getLocalStorageData from '../utils/getLocalStorageData';
    4
    5...
    6
    7const NotesList = () => {
    8 const notes = getLocalStorageData('notes');
    9
    10 const listItems = notes.map((note) => {
    11 return (
    12 <ListItem key={note.id}>
    13 <h4><Link to={`/edit/${note.id}`}>{note.title}</Link></h4>
    14 </ListItem>
    15 );
    16 });
    17
    18 return (
    19 <NotesListContainer>
    20 <List>{listItems}</List>
    21 </NotesListContainer>
    22 );
    23};
    24
    25...
    1. Update src/components/AddNoteForm.js.
    1...
    2
    3import getLocalStorageData from '../utils/getLocalStorageData';
    4
    5...
    6
    7 const handleSubmit = (e) => {
    8 const notes = getLocalStorageData('notes');
    9
    10 const noteId = uuidv4();
    11
    12 notes.push({...state, id: noteId});
    13
    14 localStorage.setItem('notes', JSON.stringify(notes));
    15
    16 e.preventDefault();
    17 }
    18
    19...
    1. Update src/components/EditNoteForm.js.
    1...
    2
    3import getLocalStorageData from '../utils/getLocalStorageData';
    4
    5...
    6
    7 useEffect(() => {
    8 const notes = getLocalStorageData('notes');
    9
    10 setAllNotes(notes);
    11
    12 const noteId = location.pathname.replace('/edit/', '');
    13
    14 const currentNote = notes.filter((note) => note.id === noteId);
    15
    16 setCurrentNote(currentNote[0]);
    17 }, []);
    18
    19...

    Langkah refactoring ini tidak harus dilakukan, namun sangat direkomendasikan, karena sebenarnya tanpa refactoring aplikasi DinoTes (Front End) sudah bisa digunakan.

    Masih banyak celah untuk kita bisa melakukan refactoring lagi.

    Sebagai contoh, masih ingat dengan prinsip clean code dimana function sebaiknya hanya melakukan satu hal?

    Perhatikan event handler handleSubmit() di AddNoteForm component, tugas dari handler ini lumayan banyak:

    1const handleSubmit = (e) => {
    2 // mengambil data
    3 const notes = getLocalStorageData('notes');
    4 //generate id
    5 const noteId = uuidv4();
    6 // menambahkan id ke note
    7 notes.push({ ...state, id: noteId });
    8 // simpan note di localStorage
    9 localStorage.setItem('notes', JSON.stringify(notes));
    10
    11 e.preventDefault();
    12};

    Kita bisa rampingkan handleSubmit() dengan membuat function untuk menambahkan note id, sehingga bisa menjadi seperti ini:

    1const handleSubmit = (e) => {
    2 // tambahkan id dan simpan data di localStorage
    3 localStorage.setItem('notes', JSON.stringify(addNoteId(notes)));
    4
    5 e.preventDefault();
    6};

    Silahkan bereksperimen.

    Update Button

    Button Save dengan button Delete perlu dibedakan, yaitu dengan membedakan warna dari kedua button tersebut.

    Step by step

    1. Update src/components/ui/Button.js
    1import styled from 'styled-components';
    2
    3const Button = styled.button`
    4 background: ${(props) => (props.danger ? '#F56565' : '#3182ce')};
    5 color: white;
    6 font-size: 1em;
    7 margin: 1rem 0;
    8 padding: 0.75rem;
    9 border: 2px solid white;
    10 border-radius: 5px;
    11`;
    12
    13export default Button;
    1. Update <Button> component pada src/components/EditNoteForm.js menjadi:
    1...
    2
    3<Button danger onClick={handleDeleteNote}>Delete</Button>
    4
    5...

    Dengan menggunakan styled-components kita dapat menggunakan props seperti pada React component.

    Pada code di atas, menambahkan props danger pada component <Button> membuat warna dari <Button> berubah.

    ✅ Hasil akhir

    update button

    Menambah Note Preview

    Kita tambahkan preview untuk setiap note di Home page untuk memudahkan user melihat sebagian isi dari notes.

    Step by step

    1. Update src/components/NotesList.js
    1import React fr--om 'react';
    2import styled from 'styled-components';
    3import { Link } from 'react-router-dom';
    4import getLocalStorageData from '../utils/getLocalStorageData';
    5
    6const NotesListContainer = styled.div`
    7 display: flex;
    8 flex-direction: column;
    9 min-width: 30vw;
    10 text-align: left;
    11 margin: 1rem;
    12 padding: 1rem;
    13 border: 2px solid #a0aec0;
    14 border-radius: 5px;
    15`;
    16
    17const List = styled.ul`
    18 list-style: none;
    19`;
    20
    21const ListItem = styled.li`
    22 margin: 0.5rem;
    23`;
    24
    25const Separator = styled.hr`
    26 width: 90%;
    27 margin: -1px;
    28 background-color: #edf2f7;
    29 color: #edf2f7;
    30`;
    31
    32const NotesList = () => {
    33 const notes = getLocalStorageData('notes');
    34
    35 const listItems = notes.map((note) => {
    36 return (
    37 <ListItem key={note.id}>
    38 <h4>
    39 <Link to={`/edit/${note.id}`}>{note.title}</Link>
    40 </h4>
    41 <p>{note.note.slice(0, 101)}</p>
    42 <Separator />
    43 </ListItem>
    44 );
    45 });
    46
    47 return (
    48 <NotesListContainer>
    49 <List>{listItems}</List>
    50 </NotesListContainer>
    51 );
    52};
    53
    54export default NotesList;

    ✅ Hasil akhir

    note preview

    Menampilkan pesan

    Kita bisa membuat DinoTes menampilkan pesan berisikan informasi bahwa note berhasil disimpan ketika user berhasil membuat sebuah note baru.

    Step by step

    1. Buat sebuah file baru bernama Message.js di folder src/components/ui.

    src/components/ui/Message.js

    1import React from 'react';
    2import styled from 'styled-components';
    3
    4const MessageContainer = styled.div`
    5 display: flex;
    6 flex-direction: column;
    7 align-items: center;
    8 justify-content: center;
    9 margin: 0.5rem;
    10 padding: 0 1rem;
    11 border: 2px solid #68d391;
    12 border-radius: 5px;
    13`;
    14
    15const Message = (props) => {
    16 const { text } = props;
    17 return (
    18 <MessageContainer>
    19 <p>{text}</p>
    20 </MessageContainer>
    21 );
    22};
    23
    24export default Message;
    1. Update src/components/AddNoteForm.js.
    1import React, { useState } from 'react';
    2import { v4 as uuidv4 } from 'uuid';
    3import { Form, FormGroup, Label, Input, TextArea } from '../components/ui/Form';
    4import Button from '../components/ui/Button';
    5import Message from '../components/ui/Message';
    6import getLocalStorageData from '../utils/getLocalStorageData';
    7
    8const AddNoteForm = () => {
    9 const [state, setState] = useState({ title: '', note: '' });
    10 const [isSuccess, setIsSuccess] = useState(false);
    11
    12 const handleTitleChange = (e) => {
    13 setState({ ...state, title: e.target.value });
    14 };
    15
    16 const handleNoteChange = (e) => {
    17 setState({ ...state, note: e.target.value });
    18 };
    19
    20 const handleSubmit = (e) => {
    21 const notes = getLocalStorageData('notes');
    22
    23 const noteId = uuidv4();
    24
    25 notes.push({ ...state, id: noteId });
    26
    27 localStorage.setItem('notes', JSON.stringify(notes));
    28
    29 setIsSuccess(true);
    30
    31 e.preventDefault();
    32 };
    33
    34 const { title, note } = state;
    35
    36 return (
    37 <>
    38 {isSuccess && <Message text="Data berhasil disimpan" />}
    39 <Form onSubmit={handleSubmit}>
    40 <FormGroup>
    41 <Label>Title</Label>
    42 <Input type="text" name="title" value={title} onChange={handleTitleChange} />
    43 </FormGroup>
    44 <FormGroup>
    45 <Label>Note</Label>
    46 <TextArea name="note" rows="12" value={note} onChange={handleNoteChange} />
    47 </FormGroup>
    48 <FormGroup>
    49 <Button type="submit">Add</Button>
    50 </FormGroup>
    51 </Form>
    52 </>
    53 );
    54};
    55
    56export default AddNoteForm;

    teknik conditional rendering digunakan untuk menampilkan pesan.

    1{
    2 isSuccess && <Message text="Data berhasil disimpan" />;
    3}

    ✅ Demo

    Membuat Git Repository

    Repository yang dimaksud disini adalah tempat untuk menyimpan code namun dengan tambahan fitur seperti version control atau content tracker.

    Git Repository adalah repository yang menggunakan Git sebagai version control system.

    Version Control System adalah sistem yang merekam setiap perubahan yang terjadi di dalam source code dari waktu ke waktu

    Selain merekam setiap perubahan yang terjadi di dalam sebuah repository, Git juga memungkinkan kita untuk undo perubahan yang sudah dibuat dan mengembalikan versi repository ke versi sebelum terjadi perubahan.

    Tentunya hal ini sangat membantu proses development sebuah aplikasi.

    Kita akan membuat Git Repository yang disimpan di Git Hosting Service Provider atau Git Provider, yaitu penyedia layanan hosting khusus Git Repository.

    Repository yang disimpan di Git provider dapat diakses dimana saja dan kapan saja, apapun jenis device yang kita gunakan.

    Beberapa contoh Git Provider:

    Saat tulisan ini dibuat Github adalah Git provider paling populer.

    Selanjutnya ikuti langkah berikut untuk membuat Git repository di GitHub kemudian menyimpan file project aplikasi DinoTes.

    1. Buat akun GitHub disini
    2. Buat Repository baru, klik New Repository dan beri nama dinotes-app
    3. Buka terminal dan navigasi ke folder dimana project DinoTes disimpan

    Sebagai contoh jika project DinoTes disimpan di folder Desktop/MyProject maka eksekusi perintah berikut:

    1cd Desktop/MyProject/dinotes-app
    1. Kemudian eksekusi perintah berikut ini:
    1git init
    2git add .
    3git commit -m "first commit"
    4git remote add origin git@github.com:{username}/dinotes-app.git
    5git push -u origin master

    Ubah {username} dengan username GitHub yang sudah dibuat.

    Source code dari Front End DinoTes dapat didownload disini atau eksekusi perintah berikut untuk cloning git repository.

    1git clone https://github.com/devsaurus-class/dinotes-app.git

    Testing

    Pada bagian ini kita hanya perlu melakukan test pada aplikasi DinoTes yang sudah dibuat.

    Sebenarnya ada metode testing yang direkomendasikan seperti Unit Testing, Integrated Testing dsb. Tetapi kita akan bahas nanti di bagian Improve App.

    Dan...

    🚀 Mission Accomplished!

    Front End DinoTes sudah selesai dibuat.