Pengenalan React Hooks
React Hooks adalah fitur baru yang diperkenalkan dalam React versi 16.8. Hooks memungkinkan pengembang untuk menggunakan state dan fitur React lainnya dalam komponen functional, yang sebelumnya hanya tersedia dalam komponen class. Ini adalah cara baru dan lebih sederhana untuk menulis komponen React tanpa menggunakan class.
Sebelum adanya Hooks, penggunaan state dan fitur lainnya dalam React terbatas pada komponen class. Namun, dengan semakin kompleksnya aplikasi React, penggunaan class component seringkali membuat kode menjadi rumit dan sulit dipelihara. Hooks diperkenalkan untuk mengatasi masalah ini dan memberikan alternatif yang lebih sederhana dan elegan dalam menulis komponen React.
Manfaat Penggunaan React Hooks:
Sederhana dan Mudah Dipahami: Hooks menyederhanakan sintaks dan logika dalam penulisan komponen React, membuatnya lebih mudah dipahami oleh pengembang, terutama bagi mereka yang baru mempelajari React.
Mengurangi Kode yang Berlebihan: Dengan menggunakan Hooks, kode menjadi lebih ringkas dan mudah dipelihara. Pengembang tidak perlu lagi menulis boilerplate code yang terkait dengan class component.
Memisahkan Logika dari Tampilan: Dengan memisahkan logika komponen dari tampilan, Hooks memungkinkan pengembang untuk lebih fokus pada struktur aplikasi dan pengelolaan state.
Meningkatkan Kinerja: Dibandingkan dengan class component, komponen functional dengan Hooks cenderung memiliki performa yang lebih baik karena overhead yang lebih rendah.
Mengenal useState Hook
useState adalah salah satu dari beberapa Hooks yang disediakan oleh React untuk mengelola state dalam komponen fungsi. Dengan menggunakan useState, kita bisa menambahkan state lokal ke dalam komponen fungsi tanpa perlu mengubahnya menjadi class component.
Selanjutnya kita persiapkan project kita, disini saya menggunakan setup project dari blog ini. Kemudian, buat file component StateComponent.jsx untuk mencoba useState Hook. Masukkan kode berikut pada StateComponent.jsx.
import React, { useState } from 'react';
export default function StateComponent() {
const [count, setCount] = useState(0);
const incrementCount = () => {
setCount(count + 1);
};
return (
<div>
<p>Nilai count: {count}</p>
<button type="button" onClick={incrementCount}>
Tambah Count
</button>
</div>
);
}
Dalam contoh di atas, kita menggunakan useState untuk menambahkan state 'count' dengan nilai awal 0. Kemudian, kita mendefinisikan fungsi 'incrementCount' yang akan dipanggil ketika tombol diklik, yang akan meningkatkan nilai count dengan 1 setiap kali dipanggil.
Dengan menggunakan useState Hook, pengelolaan state dalam komponen fungsi menjadi lebih mudah dan efektif, membantu kita dalam membangun aplikasi React yang lebih baik.
Mengenal useEffect Hook
useEffect adalah salah satu hooks yang paling sering digunakan dalam React. Hook ini memungkinkan kita untuk melakukan efek samping dalam komponen fungsi, seperti melakukan panggilan HTTP, consume data dari API, mengelola langganan, dan banyak lagi. useEffect dipanggil setiap kali komponen dirender, dan kita dapat mengontrol kapan efek tersebut dijalankan dengan menggunakan dependensi.
Untuk menggunakan useEffect, kita cukup mengimpor hook tersebut dari 'react' dan kemudian memanggilnya di dalam komponen kita. useEffect menerima dua parameter: sebuah fungsi efek yang akan dijalankan, dan sebuah array dependensi opsional yang menentukan kapan efek tersebut harus dijalankan.
import React, { useEffect, useState } from 'react';
export default function EffectComponent() {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(
'https://jsonplaceholder.typicode.com/posts'
);
if (!response.ok) {
throw new Error('Gagal memuat data');
}
const data = await response.json();
setPosts(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
fetchData();
}, []);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<div>
<h1>Data Posts</h1>
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
Dalam contoh ini, kita menggunakan API JSONPlaceholder untuk mendapatkan daftar posting. Anda dapat mengakses data melalui URL https://jsonplaceholder.typicode.com/posts
. Data yang diterima adalah dalam bentuk array objek, di mana setiap objek mewakili satu posting. Kita kemudian menggunakan useEffect untuk memuat data saat komponen dimount, dan menampilkan daftar posting tersebut dalam bentuk daftar ul.
Kapan Menggunakan useEffect?
Kita dapat menggunakan useEffect untuk berbagai hal, seperti:
Memuat data awal dari API.
Berlangganan dan membatalkan langganan dari WebSocket atau EventSource.
Melakukan manipulasi DOM setelah komponen dirender.
Menjalankan kode yang membutuhkan pembaruan setiap kali prop atau state berubah.
Contoh penerapan useEffect lainnya:
import React, { useEffect, useState } from 'react';
export default function CountComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
if (count % 2 === 0) {
console.log('UseEffect invoked');
}
}, [count]);
const increment = () => {
setCount((prevCount) => prevCount + 1);
};
const decrement = () => {
setCount((prevCount) => prevCount - 1);
};
return (
<div>
<h1>Counter</h1>
<button type="button" onClick={increment}>
Increment
</button>
<button type="button" onClick={decrement}>
Decrement
</button>
<p>Count: {count}</p>
<p>Even Count: {count % 2 === 0 ? count : count - 1}</p>
</div>
);
}
Di dalam komponen ini, kita menggunakan Hook useState
untuk membuat state bernama count
, yang akan menyimpan nilai dari hitungan yang sedang dilakukan.
Kemudian, kita menggunakan Hook useEffect
untuk melakukan sesuatu setiap kali nilai dari count
adalah bilangan genap. Dalam kasus ini, kita hanya mencetak pesan 'UseEffect invoked'
ke konsol setiap kali nilai count
adalah bilangan genap.
Kemudian, terdapat dua fungsi lainnya: increment
dan decrement
. Fungsi increment
akan menambah nilai count
dengan menggunakan fungsi updater dari setCount
, sedangkan fungsi decrement
akan mengurangi nilai count
.
Pada bagian JSX, terdapat elemen-elemen HTML yang menampilkan tombol untuk menambah dan mengurangi nilai count
, serta dua elemen <p>
yang menampilkan nilai count
dan nilai evenCount
. evenCount
dihitung secara langsung dalam JSX dengan menggunakan ekspresi ternary {count % 2 === 0 ? count : count - 1}
, yang menentukan apakah count
adalah bilangan genap atau ganjil.
Mengenal useRef Hook
Dalam pengembangan aplikasi web dengan ReactJS, seringkali kita perlu berinteraksi langsung dengan elemen DOM, menyimpan referensi ke elemen tersebut, atau mengakses nilai dari elemen input. Di sinilah useRef Hook hadir sebagai solusi yang sangat berguna.
useRef adalah salah satu dari banyak hooks bawaan yang disediakan oleh React. useRef digunakan untuk membuat referensi mutable (yang dapat berubah) ke elemen DOM atau nilai lain dalam komponen React. Ini memungkinkan kita untuk memanipulasi elemen DOM langsung dan menyimpan data di antara re-render komponen tanpa memicu re-render ulang.
Mengapa Menggunakan useRef Hook?
Mengakses Elemen DOM: useRef memungkinkan kita untuk dengan mudah mengakses elemen DOM langsung dari komponen React.
Memelihara Nilai di antara Re-render: Kita dapat menggunakan useRef untuk menyimpan nilai yang tidak mempengaruhi re-render komponen.
Mengakses dan Memanipulasi Data: useRef memungkinkan kita untuk mengakses dan memanipulasi data di dalam komponen tanpa memicu re-rendering yang tidak perlu.
Misalkan kita ingin membuat sebuah fitur di mana ketika pengguna mengklik tombol, fokus otomatis akan beralih ke input teks. Berikut adalah contoh implementasinya:
import React, { useRef } from 'react';
export default function FocusComponent() {
const inputRef = useRef(null);
const handleClick = () => {
inputRef.current.focus();
};
return (
<div>
<input type="text" ref={inputRef} />
<button type="button" onClick={handleClick}>
Focus Input
</button>
</div>
);
}
Contoh sederhana lainnya seperti saat kita menggunakan useRef untuk memberikan fokus otomatis ke input teks saat halaman dimuat.
import React, { useRef } from 'react';
export default function FocusComponent() {
const inputRef = useRef(null);
const handleClick = () => {
inputRef.current.focus();
};
return (
<div>
<input type="text" ref={inputRef} />
<button type="button" onClick={handleClick}>
Focus Input
</button>
</div>
);
}
Mengenal useContext Hook
useContext adalah salah satu dari banyak Hooks yang disediakan oleh React untuk memungkinkan kita mengakses nilai dari Context dalam komponen fungsional tanpa perlu menuliskan Consumer.
Sebelum adanya useContext, untuk mengakses nilai dari Context dalam komponen fungsional, kita harus menggunakan Consumer, yang menyebabkan penulisan kode yang lebih panjang dan kurang intuitif. Dengan adanya useContext, kita dapat mengakses nilai dari Context secara langsung dalam komponen fungsional, membuat kode lebih singkat, bersih, dan mudah dipahami.
Manfaat Penggunaan useContext:
Mengurangi tingkat penanaman prop dan prop drilling.
Membuat kode lebih bersih, singkat, dan mudah dipahami.
Memisahkan kekhawatiran tentang state global dari komponen, meningkatkan modularitas dan skalabilitas kode.
Langsung ke project sederhana, disini kita akan membuat dan menampilkan postingan. Kita akan menggunakan useContext untuk mengelola state aplikasi, seperti daftar postingan.
Buat folder context, kemudian buat file baru bernama
PostContext.jsx
. Di dalamnya, buatlah Context untuk mengelola state postingan seperti ini:import React, { createContext, useMemo, useState } from 'react'; import PropTypes from 'prop-types'; const PostContext = createContext(); function PostProvider({ children }) { const [posts, setPosts] = useState([]); const addPost = (newPost) => { setPosts([...posts, newPost]); }; const deletePost = (postId) => { setPosts(posts.filter((post) => post.id !== postId)); }; const contextValue = useMemo(() => ({ posts, addPost, deletePost }), [posts]); return ( <PostContext.Provider value={contextValue}> {children} </PostContext.Provider> ); } PostProvider.propTypes = { children: PropTypes.node.isRequired }; export { PostProvider, PostContext };
Penjelasan Kode:
Create PostContext: Pertama, kita membuat konteks baru menggunakan fungsi
createContext()
dengan variabelPostContext
. Context ini berfungsi sebagai tempat penyimpanan nilai global yang dapat diakses oleh komponen-komponen di dalamnya.PostProvider Component: Selanjutnya, kita memiliki komponen
PostProvider
, yang bertugas menyediakan nilai konteks kepada seluruh komponen yang berada di dalamnya. Di sini, kita menetapkan state dan logika terkait dengan konteks, seperti stateposts
dan fungsi-fungsiaddPost
dandeletePost
.useState Hooks: Dalam komponen
PostProvider
, kita menggunakan hookuseState
untuk mendefinisikan stateposts
. State ini akan digunakan untuk menyimpan daftar posting.addPost Function: Fungsi ini bertanggung jawab untuk menambahkan posting baru ke dalam daftar posting. Ketika dipanggil, fungsi ini akan menambahkan posting baru ke dalam daftar dengan menggunakan spread operator untuk menggabungkan posting baru dengan daftar yang sudah ada.
deletePost Function: Fungsi ini digunakan untuk menghapus posting dari daftar berdasarkan ID posting. Dalam implementasinya, kita menggunakan metode
filter()
untuk membuat daftar posting baru yang tidak termasuk posting dengan ID yang diberikan.useMemo Hook: Kita menggunakan hook
useMemo
untuk mengingat nilai konteks yang dihasilkan. Nilai ini hanya akan dihitung ulang saat nilai stateposts
berubah, sehingga membantu mengoptimalkan kinerja aplikasi.(useMemo akan di jelaskan dibawah)Return Statement: Di dalam komponen
PostProvider
, kita mengembalikanPostContext.Provider
dengan nilai konteks yang disediakan melalui propertivalue
. Dengan cara ini, nilaiposts
,addPost
, dandeletePost
dapat diakses oleh semua komponen yang berlangganan konteks ini.PropTypes: Penggunaan
PropTypes
bertujuan untuk mendefinisikan tipe properti yang diterima olehPostProvider
agar dapat digunakan sebagai panduan bagi pengembang yang menggunakan komponen ini.Export PostProvider dan PostContext: Terakhir, kita mengekspor
PostProvider
danPostContext
agar bisa digunakan oleh komponen lain di dalam aplikasi React.
Selanjutnya buat komponen
PostComponent.jsx
untuk menampilkan postingan.import React, { useContext } from 'react'; import PropTypes from 'prop-types'; import { PostContext } from '../context/PostContext'; export default function PostComponent({ post }) { const { deletePost } = useContext(PostContext); const handleDelete = () => { deletePost(post.id); }; return ( <div> <h3>{post.title}</h3> <p>{post.body}</p> <button type="button" onClick={handleDelete}> Delete </button> </div> ); } PostComponent.propTypes = { post: PropTypes.shape({ id: PropTypes.number.isRequired, title: PropTypes.string.isRequired, body: PropTypes.string.isRequired, }).isRequired, };
Penjelasan kode:
Import Statements: Kode ini dimulai dengan mengimpor React,
useContext
, danPropTypes
dari library props-types, serta mengimpor
PostContext
dari file../context/PostContext
. Ini mengatur semua dependensi yang diperlukan untuk komponenPostComponent
.PostComponent Function: Ini adalah fungsi komponen utama yang bertanggung jawab untuk merender tampilan satu posting. Diberikan objek
post
sebagai properti, komponen ini akan merender judul dan konten posting, serta tombol untuk menghapus posting.useContext Hook: Di dalam komponen, kita menggunakan hook
useContext
untuk mengakses nilai dariPostContext
. Ini memungkinkan kita untuk mengakses fungsideletePost
yang disediakan oleh penyedia konteks dan menggunakannya untuk menghapus posting.handleDelete Function: Ini adalah fungsi yang dipanggil ketika tombol hapus diklik. Ketika tombol tersebut diklik, fungsi
handleDelete
akan memanggildeletePost
dari konteks dengan ID posting sebagai argumen, yang akan menghapus posting tersebut dari daftar posting.Return Statement: Fungsi komponen mengembalikan elemen JSX yang merender judul dan konten posting, serta tombol hapus. Ketika tombol tersebut diklik, fungsi
handleDelete
akan dipanggil untuk menghapus posting.PropTypes: Digunakan untuk menentukan tipe properti yang diterima oleh komponen
PostComponent
. Propertipost
harus berupa objek dengan propertiid
,title
, danbody
, yang semuanya harus ada dan memiliki tipe yang sesuai.
Kemudian buat komponen
PostFormComponent.jsx
untuk menambahkan postingan baru.import React, { useContext, useState } from 'react'; import { PostContext } from '../context/PostContext'; export default function PostFormComponent() { const [title, setTitle] = useState(''); const [body, setBody] = useState(''); const { addPost } = useContext(PostContext); const handleSubmit = (e) => { e.preventDefault(); const newPost = { title, body, id: Date.now() }; addPost(newPost); setTitle(''); setBody(''); }; return ( <form onSubmit={handleSubmit}> <input type="text" placeholder="Title" value={title} onChange={(e) => setTitle(e.target.value)} /> <textarea placeholder="Body" value={body} onChange={(e) => setBody(e.target.value)} /> <button type="submit">Add Post</button> </form> ); }
Penjelasan Kode:
Import Statements: Kode dimulai dengan mengimpor
React
,useContext
, danuseState
dari library React. Selain itu,PostContext
diimpor dari file../context/PostContext
. Ini menetapkan semua dependensi yang dibutuhkan untuk komponenPostFormComponent
.useState Hook: Dua state lokal,
title
danbody
, dideklarasikan menggunakanuseState
. Mereka digunakan untuk melacak nilai judul dan konten posting yang dimasukkan oleh pengguna melalui formulir.useContext Hook: Digunakan untuk mengakses nilai dari
PostContext
. Dengan ini, kita dapat mengakses fungsiaddPost
yang disediakan oleh penyedia konteks.handleSubmit Function: Ini adalah fungsi yang dipanggil ketika formulir disubmit. Saat formulir disubmit, fungsi ini akan mengumpulkan nilai judul dan konten posting dari state lokal, membuat objek
newPost
dengan nilai tersebut bersama dengan ID yang dihasilkan olehDate.now()
, dan kemudian memanggil fungsiaddPost
dari konteks dengan objeknewPost
sebagai argumen. Setelah itu, state lokal untuk judul dan konten posting akan direset menjadi string kosong.Return Statement: Fungsi komponen mengembalikan elemen JSX yang berisi formulir untuk membuat posting baru. Formulir ini memiliki input untuk judul, textarea untuk konten posting, dan tombol "Add Post" yang akan memicu fungsi
handleSubmit
saat diklik.
Kemudian buat komponen
PostListComponent.jsx
untuk menamplikan list postingan.import React, { useContext, useState } from 'react'; import { PostContext } from '../context/PostContext'; export default function PostFormComponent() { const [title, setTitle] = useState(''); const [body, setBody] = useState(''); const { addPost } = useContext(PostContext); const handleSubmit = (e) => { e.preventDefault(); const newPost = { title, body, id: Date.now() }; addPost(newPost); setTitle(''); setBody(''); }; return ( <form onSubmit={handleSubmit}> <input type="text" placeholder="Title" value={title} onChange={(e) => setTitle(e.target.value)} /> <textarea placeholder="Body" value={body} onChange={(e) => setBody(e.target.value)} /> <button type="submit">Add Post</button> </form> ); }
Penjelasan Kode:
Import Statements: Kode dimulai dengan mengimpor
React
danuseContext
dari pustaka React. Selain itu,PostContext
diimpor dari file../context/PostContext
, danPostComponent
diimpor dari file./PostComponent
. Ini menetapkan semua dependensi yang dibutuhkan untuk komponenPostListComponent
.useContext Hook: Digunakan untuk mengakses nilai dari
PostContext
. Dengan ini, kita dapat mengakses daftar posting yang disediakan oleh penyedia konteks.Return Statement: Fungsi komponen mengembalikan elemen JSX yang berisi daftar posting. Ini dilakukan dengan menggunakan metode
map
untuk menghasilkan elemenPostComponent
untuk setiap posting dalam daftarposts
. SetiapPostComponent
menerima proppost
yang berisi detail posting, serta propkey
yang unik untuk membantu React dalam melakukan reconciling dan re-rendering komponen dengan efisien.
Selanjutnya di App.jsx, kita akan menggunakan
PostProvider
yang sudah kita buat sebelumnya untuk menyediakan state postingan kepada semua komponen di dalam aplikasi.import React from 'react'; import './App.css'; import { PostProvider } from './context/PostContext'; import PostFormComponent from './components/PostFormComponent'; import PostListComponent from './components/PostListComponent'; function App() { return ( <PostProvider> <div> <h1>Postingan</h1> <PostFormComponent /> <PostListComponent /> </div> </PostProvider> ); } export default App;
Penjelasan Kode:
Import Statements: Kode dimulai dengan mengimpor React dan file CSS yang diperlukan untuk styling (
'./App.css'
). Selain itu,PostProvider
diimpor dari file'./context/PostContext'
, danPostFormComponent
sertaPostListComponent
diimpor dari file komponen masing-masing.Elemen JSX: Di dalam fungsi komponen
App
, kita memiliki elemen JSX yang berisi elemen-elemen berikut:<PostProvider>
: Ini adalah komponen yang menyediakan konteks untuk komponen-komponen di dalamnya. Dengan menyediakan konteks, komponen-komponen di dalamnya dapat mengakses dan berbagi data tanpa harus melewatkan props secara langsung.<div>
: Ini adalah elemen div yang digunakan untuk merangkai elemen-elemen dalam aplikasi.<h1>
: Ini adalah elemen heading yang menampilkan judul aplikasi.<PostFormComponent />
: Ini adalah komponen yang digunakan untuk menampilkan formulir tambah posting.<PostListComponent />
: Ini adalah komponen yang digunakan untuk menampilkan daftar posting.
Mengenal useReducer Hook
useReducer
adalah hooks yang mirip dengan useState
, namun lebih kuat dan fleksibel untuk mengelola state dalam komponen fungsional. Dengan useReducer
, kita dapat mengelola state yang lebih kompleks dan melakukan update state berdasarkan aksi tertentu.
Beberapa kelebihan penggunaan useReducer
adalah:
Lebih cocok untuk mengelola state yang kompleks dan bergantung pada aksi tertentu.
Memisahkan logika state dari komponen, sehingga memudahkan untuk pengujian dan pemeliharaan.
Memungkinkan penggunaan context untuk berbagi state di antara komponen tanpa prop drilling.
Berikut adalah contoh aplikasi sederhana yang memungkinkan pengguna untuk menambah, menghapus, dan menyelesaikan tugas-tugas (todo).
import React, { useReducer, useState } from 'react';
const initialState = {
todos: [],
};
const reducer = (state, action) => {
switch (action.type) {
case 'ADD_TODO':
return {
todos: [
...state.todos,
{ id: Date.now(), text: action.payload, completed: false },
],
};
case 'TOGGLE_TODO':
return {
todos: state.todos.map((todo) =>
todo.id === action.payload
? { ...todo, completed: !todo.completed }
: todo
),
};
case 'DELETE_TODO':
return {
todos: state.todos.filter((todo) => todo.id !== action.payload),
};
default:
return state;
}
};
export default function TodoComponent() {
const [text, setText] = useState('');
const [state, dispatch] = useReducer(reducer, initialState);
const handleSubmit = (e) => {
e.preventDefault();
if (!text.trim()) return;
dispatch({ type: 'ADD_TODO', payload: text });
setText('');
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
/>
<button type="submit">Add Todo</button>
</form>
<ul>
{state.todos.map((todo) => (
<li key={todo.id}>
<button type='button'
style={{
textDecoration: todo.completed ? 'line-through' : 'none',
}}
onClick={() =>
dispatch({ type: 'TOGGLE_TODO', payload: todo.id })
}
>
{todo.text}
</button>
<button type='button'
onClick={() =>
dispatch({ type: 'DELETE_TODO', payload: todo.id })
}
>
Delete
</button>
</li>
))}
</ul>
</div>
);
}
Berikut penjelasan detailnya:
initialState
: Ini adalah objek yang berisi keadaan awal dari state kita. Dalam kasus ini,initialState
hanya memiliki satu properti yaitutodos
, yang merupakan array kosong yang akan menyimpan daftar tugas.reducer
adalah sebuah fungsi yang mengelola perubahan state berdasarkan tindakan (action) yang diterima. Fungsi reducer menerima dua parameter, yaitu state saat ini dan action yang dijalankan. Berdasarkan jenis action, fungsi reducer akan mengembalikan state baru.Dalam fungsi reducer di atas, kita menentukan bagaimana state akan berubah berdasarkan jenis action yang diterima. Misalnya:
Saat jenis action adalah
'ADD_TODO'
, kita akan menambahkan sebuah todo baru ke dalam array todos.Saat jenis action adalah
'TOGGLE_TODO'
, kita akan menandai sebuah todo sebagai selesai atau belum selesai.Saat jenis action adalah
'DELETE_TODO'
, kita akan menghapus sebuah todo dari array todos.
Setiap kasus akan mengembalikan state baru yang sesuai dengan perubahan yang diinginkan, sementara kasus default akan mengembalikan state tanpa perubahan.
Bagian
TodoList
adalah komponen utama yang bertanggung jawab untuk menampilkan daftar tugas (todos) dan mengelola interaksi pengguna terhadapnya. Berikut adalah penjelasan komponenTodoList
:useState
: React hookuseState
digunakan untuk menyimpan state lokal pada komponen fungsional. Di sini, kita menggunakanuseState
untuk menyimpan nilai input pengguna yang merupakan teks untuk todo baru.React hook
useReducer
digunakan untuk mengelola state aplikasi kompleks dengan menggunakan konsep reducer dan action. Di sini, kita menggunakanuseReducer
untuk mengelola daftar tugas (todos) dengan reducer yang telah didefinisikan sebelumnya.handleSubmit
: Ini adalah fungsi yang dipanggil saat pengguna mengirimkan formulir penambahan tugas. Fungsi ini membatalkan perilaku bawaan formulir (pengiriman ulang halaman) dan menambahkan tugas baru ke dalam daftar menggunakan action'ADD_TODO'
.Di dalam elemen
form
, kita memiliki sebuah input teks yang akan digunakan pengguna untuk menambahkan tugas baru. Nilai input diatur oleh statetext
, dan setiap perubahan pada input akan memperbarui nilaitext
menggunakansetText
.Di bawahnya, kita memiliki elemen
ul
yang menampilkan daftar tugas. Setiap tugas dirender sebagai elemenli
, dengan dua tombol yang memungkinkan pengguna untuk menandai tugas sebagai selesai (TOGGLE_TODO
) atau menghapusnya (DELETE_TODO
). Aksi ini dipicu olehdispatch
yang memicu action yang sesuai.state.todos
adalah array dari seluruh tugas yang disimpan dalam state. Setiap tugas dirender sebagai elemenli
, dan dua tombol diberikan untuk setiap tugas untuk melakukan aksi sesuai dengan kebutuhan pengguna.
Mengenal useMemo Hook
useMemo
adalah salah satu dari hooks yang disediakan oleh React untuk mengoptimalkan performa komponen dalam aplikasi React. Fungsi useMemo
digunakan untuk memoisasi nilai yang dihitung secara komputasional sehingga nilai tersebut hanya dihitung ulang ketika dependensinya berubah.
Ketika menggunakan useMemo
, Kita memberikan sebuah fungsi atau ekspresi yang akan dievaluasi, serta array dependencies yang menentukan kapan nilai tersebut harus dihitung ulang. Ketika salah satu nilai dalam array dependencies berubah, React akan menghitung kembali nilai dari fungsi atau ekspresi yang diberikan, dan memperbarui nilai memoized tersebut.
Penggunaan useMemo
biasanya berguna dalam situasi di mana Anda memiliki perhitungan yang intensif secara komputasional atau ketika Anda ingin menghindari pengulangan perhitungan yang tidak perlu di setiap pembaharuan komponen. Dengan memanfaatkan useMemo
, Anda dapat meningkatkan kinerja aplikasi Anda dengan mengoptimalkan proses perhitungan yang diperlukan.
Perbedaan antara useMemo, useState dan useEffect
useMemo
, useState
, dan useEffect
adalah tiga hooks yang berbeda dalam React, dan masing-masing memiliki peran dan fungsi yang unik:
useMemo:
useMemo
digunakan untuk memoization nilai yang dihitung secara komputasional.Ini berguna saat Anda ingin menghindari penghitungan yang mahal secara berulang kali dalam suatu komponen.
useMemo
mengambil dua argumen: sebuah fungsi yang mengembalikan nilai yang ingin dimemoisasi, dan sebuah array dependencies yang menentukan kapan nilai memoized harus dihitung ulang.Ini hanya menghitung ulang nilainya saat salah satu dependencies berubah.
Penggunaan
useMemo
berguna untuk mengoptimalkan kinerja komponen dengan menghindari perhitungan yang tidak perlu.
useState:
useState
digunakan untuk menyimpan dan mengelola state dalam komponen React.Ini memungkinkan komponen untuk menyimpan dan memperbarui data secara lokal.
Setiap kali state berubah, komponen akan dirender ulang untuk mencerminkan perubahan tersebut.
Ini tidak memengaruhi kinerja secara langsung, tetapi digunakan untuk menyimpan data yang relevan dengan keadaan komponen.
useEffect:
useEffect
digunakan untuk melakukan efek samping di dalam komponen React.Ini digunakan untuk melakukan tugas-tugas yang tidak mempengaruhi tampilan langsung, seperti berlangganan pada data eksternal, mengelola siklus hidup komponen, atau membersihkan sumber daya.
useEffect
dapat digunakan untuk melakukan sesuatu setelah render komponen, dan dapat menerima dependencies yang akan memicu efek tersebut untuk dijalankan ulang ketika nilai dependencies berubah.Ini memengaruhi kinerja jika efeknya mahal atau dilakukan secara berulang-ulang tanpa perlu.
Jadi, perbedaan utama antara useMemo
, useState
, dan useEffect
adalah bahwa useMemo
digunakan untuk memoization nilai yang dihitung secara komputasional, useState
digunakan untuk mengelola state dalam komponen, dan useEffect
digunakan untuk melakukan efek samping di dalam komponen. Semua tiga hooks ini memainkan peran yang berbeda dalam pengembangan aplikasi React dan digunakan untuk tujuan yang berbeda.
Kapan menggunakan useMemo
Berikut adalah beberapa kasus penggunaan useMemo
dalam pembuatan web:
Pengolahan Data atau Perhitungan yang Mahal: Misalnya, ketika Anda memiliki data yang besar atau perhitungan yang kompleks yang dilakukan dalam komponen, Anda dapat menggunakan
useMemo
untuk mememoize hasil perhitungan tersebut. Ini membantu menghindari perhitungan yang mahal setiap kali komponen dirender ulang.Pemanggilan API: Ketika Anda membuat pemanggilan API untuk mendapatkan data, Anda dapat menggunakan
useMemo
untuk mememoize hasil pemanggilan API tersebut. Ini memastikan bahwa pemanggilan API hanya dilakukan ketika dependensi (misalnya, prop atau state) yang berubah nilainya, dan memungkinkan kembali menggunakan hasil pemanggilan API yang dimemoize saat komponen dirender ulang.Penguraian String: Ketika Anda memiliki penguraian string yang kompleks atau operasi manipulasi string yang membutuhkan waktu lama, Anda dapat menggunakan
useMemo
untuk mememoize hasil penguraian string tersebut. Ini membantu menghindari penguraian string yang dilakukan setiap kali komponen dirender ulang.Komputasi Kompleks Lainnya: Ada banyak kasus di mana komputasi kompleks diperlukan dalam pembuatan web, seperti perhitungan matematis, pengolahan data, atau manipulasi struktur data. Dalam kasus-kasus ini, Anda dapat menggunakan
useMemo
untuk mememoize hasil komputasi tersebut dan mencegah perhitungan yang mahal setiap kali komponen dirender ulang.
Langsung saja ke contoh sederhana penggunaan useMemo
, buat folder utils kemudian buat file math.js. isi seperti berikut:
export function factorial(n) {
let result = 1;
for (let i = 2; i <= n; i+=1) {
result *= i;
}
return result;
}
export function permutation(totalItems, selectedItems) {
return factorial(totalItems) / factorial(totalItems - selectedItems);
}
export function combination(totalItems, selectedItems) {
return (
factorial(totalItems) /
(factorial(selectedItems) * factorial(totalItems - selectedItems))
);
}
Buat file MemoComponent.jsx, kemudian isi seperti ini
import React, { useMemo, useState } from 'react';
import { combination, permutation } from '../utils/math';
export default function MemoComponent() {
const [totalItems, setTotalItems] = useState(0);
const [selectedItems, setSelectedItems] = useState(0);
const permutationResult = useMemo(() => {
console.log('Menghitung permutasi...');
return permutation(totalItems, selectedItems);
}, [totalItems, selectedItems]);
const combinationResult = useMemo(() => {
console.log('Menghitung kombinasi...');
return combination(totalItems, selectedItems);
}, [totalItems, selectedItems]);
return (
<div>
<h1>Contoh Penggunaan useMemo di React</h1>
<p>Masukkan jumlah total item:</p>
<input
type="number"
value={totalItems}
onChange={(e) => setTotalItems(parseInt(e.target.value, 10))}
/>
<p>Masukkan jumlah item yang dipilih:</p>
<input
type="number"
value={selectedItems}
onChange={(e) => setSelectedItems(parseInt(e.target.value, 10))}
/>
<p>Permutasi: {permutationResult}</p>
<p>Kombinasi: {combinationResult}</p>
</div>
);
}
Penjelasan kode :
import React, { useMemo, useState } from 'react';
: Baris ini mengimpor React dan hooksuseMemo
danuseState
dari pustaka React. Hooks digunakan untuk mengelola state dan efek samping di dalam functional component.import { combination, permutation } from '../utils/math';
: Baris ini mengimpor fungsicombination
danpermutation
dari filemath.js
yang terletak di dalam folderutils
. Filemath.js
mungkin berisi definisi fungsi-fungsi matematika seperti permutasi, kombinasi, dll.export default function MemoComponent() { ... }
: Ini adalah deklarasi dari functional component bernamaMemoComponent
. Component ini menangani logika dan tampilan terkait permutasi dan kombinasi.const [totalItems, setTotalItems] = useState(0);
danconst [selectedItems, setSelectedItems] = useState(0);
: Dua statetotalItems
danselectedItems
digunakan untuk menyimpan jumlah total item dan jumlah item yang dipilih. Mereka diinisialisasi dengan nilai awal 0 menggunakanuseState
hook.const permutationResult = useMemo(() => { ... }, [totalItems, selectedItems]);
: Ini adalah penggunaan hookuseMemo
. Hook ini menghitung nilai permutasi hanya ketika nilai daritotalItems
atauselectedItems
berubah. Hasil perhitungan disimpan dalam variabelpermutationResult
.const combinationResult = useMemo(() => { ... }, [totalItems, selectedItems]);
: Sama seperti penggunaanuseMemo
sebelumnya, hook ini digunakan untuk menghitung nilai kombinasi hanya ketika nilai daritotalItems
atauselectedItems
berubah. Hasil perhitungan disimpan dalam variabelcombinationResult
.Di dalam render function, terdapat elemen
<input>
untuk memasukkan jumlah total item dan jumlah item yang dipilih. FungsisetTotalItems
dansetSelectedItems
digunakan untuk mengubah nilai statetotalItems
danselectedItems
ketika nilai input berubah.Terakhir, hasil perhitungan permutasi dan kombinasi ditampilkan di dalam elemen
<p>
.
Dengan menggunakan useMemo
, perhitungan permutasi dan kombinasi hanya dilakukan jika ada perubahan nilai totalItems
atau selectedItems
, sehingga meningkatkan kinerja aplikasi.
Mengenal useCallback Hook
useCallback
adalah salah satu dari banyak Hooks yang disediakan oleh React untuk mengelola state dan efek samping dalam komponen fungsional. Tujuan utama useCallback
adalah untuk mengoptimalkan performa aplikasi React dengan memori caching dan menghindari pembuatan ulang fungsi yang sama setiap kali komponen dirender ulang.
Dalam konteks penggunaan, useCallback
digunakan untuk menghindari pembuatan ulang fungsi yang ditentukan setiap kali komponen dirender ulang. Misalnya, dalam sebuah komponen, kita mungkin memiliki fungsi yang dilewatkan sebagai prop ke komponen turunan. Tanpa useCallback
, setiap kali komponen induk dirender ulang, fungsi tersebut akan dibuat ulang, bahkan jika prop yang dilewatkan ke komponen turunan tetap sama. Hal ini dapat menyebabkan overhead yang tidak perlu dan mengurangi performa aplikasi.
Dengan menggunakan useCallback
, kita dapat memastikan bahwa fungsi tersebut hanya dibuat ulang jika dependensi yang ditentukan berubah. Dengan demikian, kita dapat menghindari pembuatan ulang fungsi yang tidak perlu dan meningkatkan performa aplikasi secara keseluruhan.
Perbedaan useCallback dan useMemo:
Meskipun keduanya (useCallback
dan useMemo
) memiliki tujuan untuk mengoptimalkan performa dalam aplikasi React dengan menghindari pembuatan ulang nilai, mereka memiliki perbedaan dalam cara mereka bekerja dan kapan sebaiknya digunakan.
useCallback:
useCallback
digunakan untuk menghindari pembuatan ulang fungsi yang sama setiap kali komponen dirender ulang.Ini mengambil dua argumen: fungsi yang akan dikelola dan array dependensi.
Ketika salah satu dependensi dalam array berubah nilainya, fungsi akan dibuat ulang. Jika tidak ada dependensi yang berubah, versi yang di-memoized dari fungsi akan digunakan kembali.
Biasanya digunakan untuk menghindari pembuatan ulang prop berupa fungsi yang dilewatkan ke komponen turunan.
useMemo:
useMemo
digunakan untuk menghindari pembuatan ulang nilai yang dihitung secara terkait dengan render komponen.Ini mengambil dua argumen: sebuah fungsi yang mengembalikan nilai yang akan dimemoize, dan sebuah array dependensi.
Nilai yang dihitung akan dimemoize dan hanya dihitung ulang jika salah satu dependensi dalam array berubah nilainya.
Biasanya digunakan untuk menghindari pembuatan ulang nilai yang dihitung, seperti komputasi yang mahal, penguraian string, atau pemanggilan API.
Jadi, perbedaan utama antara useCallback
dan useMemo
adalah dalam cara mereka digunakan: useCallback
untuk fungsi dan useMemo
untuk nilai yang dihitung.
Selanjutnya berikut contoh sederhana penggunaan useCallback, pertama buat file ChildComponent.jsx, kemudian isi seperti berikut:
import React from 'react'
import PropTypes from 'prop-types';
export default function ChildComponent({increment}) {
return (
<div>
<h2>Child Component</h2>
<button type='button' onClick={increment}>Increment Count from Child</button>
</div>
);
}
ChildComponent.propTypes = {
increment: PropTypes.func.isRequired
};
Penjelasan kode:
Import React and PropTypes: Kita mengimpor React dan PropTypes untuk membuat dan memvalidasi komponen React.
Functional Component:
ChildComponent
adalah komponen fungsional yang sederhana. Ini menerima satu prop bernamaincrement
.Rendering: Di dalam
ChildComponent
, kita merender sebuah elemendiv
yang berisi judulh2
dan sebuah tombol.onClick Event: Saat tombol diklik, fungsi
increment
yang diterima dari komponen induk (parent) akan dipanggil.PropTypes: Properti
increment
harus berupa sebuah fungsi, dan itu merupakan hal yang wajib (required) untuk digunakan. PropTypes digunakan untuk memastikan tipe data yang diterima oleh properti sesuai dengan yang diharapkan.
Kemudian buat file ParentComponent.jsx, dan isi seperti berikut :
import React, { useCallback, useState } from 'react';
import ChildComponent from './ChildComponent';
export default function ParentComponent() {
const [count, setCount] = useState(0);
const incrementCount = useCallback(() => {
setCount((prevCount) => prevCount + 1);
}, []);
return (
<div>
<h2>Parent Component</h2>
<p>Count: {count}</p>
<button type="button" onClick={incrementCount}>
Increment Count
</button>
<ChildComponent increment={incrementCount} />
</div>
);
}
import React, { useCallback, useState } from 'react';
: Kode ini mengimpor modul React serta hooksuseCallback
danuseState
dari pustaka React.export default function ParentComponent() { ... }
: Ini adalah deklarasi dari komponen ParentComponent yang akan diekspor untuk digunakan di tempat lain dalam aplikasi.const [count, setCount] = useState(0);
: Ini adalah pemanggilan useState hook untuk membuat statecount
dan fungsisetCount
yang akan digunakan untuk mengelola nilaicount
. Nilai awal daricount
adalah 0.const incrementCount = useCallback(() => { ... }, []);
: Ini adalah pemanggilan useCallback hook. Di dalamnya, kita mendefinisikan fungsiincrementCount
yang bertugas untuk meningkatkan nilaicount
setiap kali dipanggil. Karena dependensi kosong ([]
), fungsi ini tidak akan di-recreated ketika komponen di-render ulang.<button type="button" onClick={incrementCount}>Increment Count</button>
: Ini adalah tombol yang ketika diklik akan memanggil fungsiincrementCount
yang telah didefinisikan sebelumnya. Dengan demikian, ketika tombol ini diklik, nilaicount
akan bertambah.<ChildComponent increment={incrementCount} />
: Ini adalah pemanggilan komponen ChildComponent yang telah dibuat sebelumnya. Propertiincrement
dilewatkan ke ChildComponent, yang nilainya adalah referensi ke fungsiincrementCount
. Ini memungkinkan ChildComponent untuk menggunakan fungsi tersebut untuk melakukan peningkatancount
di dalamnya.
Dengan menggunakan useCallback
, kita memastikan bahwa fungsi incrementCount
tidak akan di-recreated setiap kali komponen ParentComponent di-render ulang, yang dapat mengoptimalkan performa aplikasi.
Kasus lain, misalkan kita memiliki aplikasi React yang menampilkan daftar item yang dapat diperbarui secara dinamis. Setiap item memiliki tombol untuk menghapusnya dari daftar. Saat tombol hapus ditekan, kita perlu memperbarui daftar dengan item yang dihapus.
Jika kita membuat fungsi penghapus item di setiap iterasi daftar, setiap kali daftar diperbarui, fungsi-fungsi tersebut akan dibuat kembali. Ini dapat menyebabkan kinerja yang buruk jika daftar memiliki banyak item.
Kita dapat menggunakan useCallback
untuk menyimpan referensi ke fungsi penghapus item, sehingga fungsi tersebut tidak dibuat ulang setiap kali komponen di-render ulang. contohnya kita bisa buat ItemComponent.jsx dan ItemListComponent.jsx
Link Repository untuk blog ini :
https://github.com/arief2020/blog-introduction-reactHook
Kesimpulan
Dalam blog "Pengenalan React Hooks", kita telah mempelajari berbagai hooks yang tersedia dalam React. Berikut adalah kesimpulan dari materi yang telah dibahas:
useState: Hooks ini memungkinkan kita untuk menggunakan state dalam komponen functional. Kita dapat menyimpan dan memperbarui nilai state serta mengaksesnya dalam komponen tanpa perlu menggunakan class.
useEffect: Digunakan untuk menangani efek samping dalam komponen React, seperti melakukan pembaruan DOM, berlangganan data, atau membersihkan sumber daya. Kita dapat menggunakan useEffect untuk menjalankan kode setelah setiap render atau untuk mengatur "efek samping" yang bergantung pada perubahan state atau props.
useContext: Hooks ini memungkinkan kita untuk mengakses konteks (context) dalam komponen functional. Dengan useContext, kita dapat menghindari prop drilling dan dengan mudah mengambil nilai dari konteks induk.
useReducer: Mirip dengan useState, tetapi lebih cocok untuk mengelola state yang lebih kompleks atau dalam kasus di mana perubahan state bergantung pada state sebelumnya atau aksi yang dikirimkan. Penggunaan useReducer dapat membuat kode lebih terstruktur dan mudah dipahami dalam kasus-kasus tertentu.
useMemo: Hooks ini digunakan untuk mengoptimalkan kinerja dengan menyimpan nilai yang dihitung secara berulang-ulang. Kita dapat menggunakan useMemo untuk menghindari perhitungan yang mahal secara komputasi di setiap render.
useCallback: Digunakan untuk menghindari pembuatan ulang fungsi yang sama di setiap render. Ini berguna ketika kita ingin mencegah perubahan tidak perlu pada props turun ke komponen yang bergantung pada referensi fungsi yang stabil.
Dengan memahami dan menggunakan berbagai hooks ini, kita dapat meningkatkan efisiensi, kinerja, dan keterbacaan kode dalam pengembangan aplikasi React. Dengan kemampuan untuk menggunakan state dan fitur-fitur React lainnya dalam komponen functional, React Hooks membuka banyak kemungkinan baru dalam pengembangan aplikasi front-end modern.