Search by

    Terakhir diperbaharui: Dec 24, 2020

    Search & Sorting

    Fitur selanjutnya yang akan kita tambahkan ke aplikasi DinoTes adalah fitur Search & Sorting.

    • Search, menambahkan sebuah search bar atau kolom pencarian untuk memudahkan user mencari note
    • Sorting, menambahkan sebuah menu dropdown agar user bisa mengurutkan note berdasarkan waktu terakhir note diupdate

    Kedua fitur ini bisa ditambahkan tanpa menginstall library external / third party.

    Search

    Untuk membuat fitur ini kita akan gunakan konsep filtering, yaitu menampilkan note yang mengandung kata yang sama dengan kata kunci atau keyword yang dimasukan oleh user.

    Gambar

    Persiapan

    Clone repository dari aplikasi DinoTes disini.

    Install dependency dengan jalankan perintah yarn install atau npm install.

    Step by Step

    Buat sebuah component search bar atau kolom pencarian pada halaman utama aplikasi.

    1const SearchBar = tw.input`
    2 my-4 p-2
    3 text-left
    4 border rounded
    5 focus:outline-none focus:ring focus:border-blue-300`;

    Tempatkan SearchBar tepat di atas component NotesListContainer.

    src/components/NotesList.js

    1...
    2 return (
    3 <>
    4 <SearchBar placeholder='Search Notes...' />
    5 <NotesListContainer>{content}</NotesListContainer>
    6 </>
    7 );
    8...

    Karena jumlah component lebih dari satu maka tempatkan SearchBar dan NotesListContainer dalam satu container.

    1...
    2 return (
    3 <Container>
    4 <SearchBar placeholder='Search Notes...' />
    5 <NotesListContainer>{content}</NotesListContainer>
    6 </Container>
    7 );
    8...

    Hasilnya

    search bar

    Update slice

    Karena aplikasi DinoTes menggunakan Redux, kita perlu menambahkan sebuah function pada file slice yang bertugas untuk melakukan filter terhadap data notes.

    Tambahkan function berikut pada file src/features/notes/notesSlice.js:

    1export const getFilteredNotes = (state, keyword) => {
    2 if (keyword) {
    3 const isKeywordExist = (array, string) => array.toLowerCase().includes(string);
    4
    5 return state.notes.data.filter((note) => isKeywordExist(note.note, keyword) || isKeywordExist(note.title, keyword));
    6 }
    7 return state.notes.data;
    8};

    Function di atas akan melakukan pengecekan apakah keyword yang dicari bisa ditemukan di dalam judul atau isi dari note.

    Update NotesList.js

    Langkah terakhir adalah menambahkan handler dan update function getAllNotes dengan function getFilteredNotes.

    src/components/NotesList.js

    1import React, { useEffect, useState } from 'react';
    2import tw from 'twin.macro';
    3import { Link } from 'react-router-dom';
    4import { useSelector, useDispatch } from 'react-redux';
    5import { fetchNotes, getFilteredNotes } from '../features/notes/notesSlice';
    6import Container from './ui/Container';
    7
    8const NotesListContainer = tw.div`grid grid-cols-1 md:grid-cols-3 gap-4 my-8`;
    9const Card = tw.div`text-left p-4 border rounded-md`;
    10const Title = tw.h4`text-lg font-semibold text-purple-900`;
    11const SearchBar = tw.input`my-4 p-2 text-left border rounded focus:outline-none focus:ring focus:border-blue-300`;
    12
    13const NotesList = () => {
    14 const [keyword, setKeyword] = useState('');
    15 const dispatch = useDispatch();
    16 const notes = useSelector((state) => getFilteredNotes(state, keyword));
    17 const notesStatus = useSelector((state) => state.notes.status);
    18 const error = useSelector((state) => state.notes.error);
    19
    20 useEffect(() => {
    21 if (notesStatus === 'idle') {
    22 dispatch(fetchNotes());
    23 }
    24 }, [notesStatus, dispatch]);
    25
    26 const handleChange = (e) => {
    27 setKeyword(e.target.value);
    28 };
    29
    30 let content;
    31
    32 if (notesStatus === 'loading') {
    33 content = <div>Loading...</div>;
    34 } else if (notesStatus === 'succeeded') {
    35 content = notes.map((note) => {
    36 return (
    37 <Card key={note._id}>
    38 <Title>
    39 <Link to={`/edit/${note._id}`}>{note.title}</Link>
    40 </Title>
    41 <p>{note.note.slice(0, 101)}</p>
    42 </Card>
    43 );
    44 });
    45 } else if (notesStatus === 'failed') {
    46 content = <div>{error}</div>;
    47 }
    48
    49 return (
    50 <Container>
    51 <SearchBar placeholder="Search Notes..." onChange={handleChange} />
    52 <NotesListContainer>{content}</NotesListContainer>
    53 </Container>
    54 );
    55};
    56
    57export default NotesList;

    Hasil Akhir: