-
{friends.map((friend, index) => (
- name: {friend.name}{" "} age: {friend.age} ))}
Hooks merupakan fitur baru di React 16.8. Dengan Hooks, kita dapat menggunakan state dan fitur React yang lain tanpa perlu menulis sebuah kelas baru. Salah satunya yaitu useState diperkenalkan melalui kode di bawah ini.
import React, { useState } from 'react';
function Example() {
// Mendeklarasikan variabel state baru, yaitu "count"
const [count, setCount] = useState(0);
return (
Anda mengklik {count} kali
);
}
Dengan referensi kode di atas useState merupakan Hook. useState di panggil dalam function component untuk menambahkan suatu state lokal. React akan menyimpan state antar render. useState memberikan dua hal:
Anda dapat memanggil fungsi ini dari sebuah event handler atau dimanapun. Hal ini serupa dengan this.setState pada kelas, tetapi tidak menggabungkan state lama dan baru menjadi satu.
Anda dapat menggunakan Hook untuk state lebih dari sekali pada satu komponen:
function ContohDenganBanyakState() {
// Deklarasi banyak variabel state!
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('pisang');
const [todos, setTodos] = useState([{ text: 'Belajar Hooks' }]);
// ...
}
Tidak hanya variable, useState juga dapat berisi array.
Sebelum mempelajari cara memanipulasi Array dengan useState kita harus mendefiniskannya terlebih dahulu.
import React, { useState } from 'react';
export default function Example() {
const [todo, setTodo]= useState("")
const [todos, setTodos] = useState([]);
const addTodos = (e) => {
setTodos(prevTodo => [...prevTodo, todo]);
}
return (
{todos.map((row,key)=>
- {row}
)}
setTodo(e.target.value)} />
);
}
import { useState } from "react";
const App = () => {
const [friends, setFriends] = useState(friendsArray);
const handleAddFriend = () => {
setFriends((prevFriends) => [
...prevFriends, {
name: "Random Friend Name",
age: 20,
},
]);
};
return (
{friends.map((friend, index) => (
-
name: {friend.name}{" "}
age: {friend.age}
))}
);
};
export default App;
const friendsArray = [
{
name: "John",
age: 19,
},
{
name: "Candy",
age: 18,
},
{
name: "mandy",
age: 20,
},
];
import { useState } from "react";
const App = () => {
const [friends, setFriends] = useState(friendsArray);
const handleSecondFriend = () => {
setFriends(
friends.map((friend) =>
// Here you accept a id argument to the function and replace it with hard coded 🤪 2, to make it dynamic.
friend.id === 2
? { ...friend, name: "Changed Name" }
: { ...friend }
)
);
};
return (
{friends.map((friend, index) => (
-
name: {friend.name}{" "}
age: {friend.age}
))}
);
};
export default App;
const friendsArray = [
{
id:1,
name: "John",
age: 19,
},
{
id:2,
name: "Candy",
age: 18,
},
{
id:3,
name: "mandy",
age: 20,
},
];
import { useState } from "react";
const App = () => {
const [friends, setFriends] = useState(friendsArray);
const removeFriendByName = () => {
setFriends((current) => current.filter((friend)=>friend.name !== "Candy"));
}
return (
{friends.map((friend, index) => (
-
name: {friend.name}{" "}
age: {friend.age}
))}
);
};
export default App;
const friendsArray = [
{
id:1,
name: "John",
age: 19,
},
{
id:2,
name: "Candy",
age: 18,
},
{
id:3,
name: "mandy",
age: 20,
},
];
Hook useEffect, menambahkan kemampuan untuk melakukan “efek samping” dari sebuah function component. Hook ini memiliki fungsi yang sama dengan componentDidMount, componentDidUpdate, dan componentDidMount pada kelas React, tetapi disatukan menjadi satu fungsi.
Sebagai contoh, komponen berikut menetapkan judul dokumen setelah React memperbarui DOM:
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// Sama seperti componentDidMount dan componentDidUpdate:
useEffect(() => {
// Memperbarui judul dokumen menggunakan API browser
document.title = `Anda klik sebanyak ${count} kali`;
});
return (
Anda klik sebanyak {count} kali
);
}
Jalankan pada browser, anda akan melihat setiap ada perubahan pada variable count, maka document title anda akan ikut berubah, sama seperti componentDidUpdate.
Sekarang ubah kodenya menjadi :
useEffect(() => {
// Memperbarui judul dokumen menggunakan API browser
document.title = `Anda klik sebanyak ${count} kali`;
,[]},
Setelah dijalankan dokumen title hanya berubah sekali menjadi “Anda klik sebanyak 0 kali” dan berhenti disitu walaupun button terus di Klik, berarti useEffect hanya berjalan 1 kali saat pertama kali dijalankan mirip seperti componentDidMount.
Nah untuk penerapan componentWillUnmount kita akan membuat kode yang berbeda untuk simulasinya. Berikut kodenya
import { useState, useEffect } from 'react';
export default function App() {
const [boolean,setBoolean] = useState(true);
const toggleBoolean = () => setBoolean((prevState) => !prevState);
return(
{ boolean ?
:
}
);
}
function Component1() {
useEffect(() => {
console.log("Component1 has mounted...");
return () => { console.log("Component1 has unmounted...")};
},[]);
return(
Component1
);
}
function Component2() {
return(
Component2
);
}
Jalankan, lalu buka Developer Tool tab Console. Akan muncul log “Component 1 mounted”… saat pertama kali dijalankan, lalu saat Toggle di klik Componen 1 akan hilang dan Component 2 akan mucul, perhatikan tab Console akan muncul log “Component 1 unmounted”
Ada dua fungsi yang akan kita gunakan yaitu :
Contoh penerapannya sebagai berikut
import { useState, createContext, useContext } from "react";
const UserContext = createContext();
function Component1() {
const [user, setUser] = useState("Jesse Hall");
return (
{`Hello ${user}!`}
);
}
function Component2() {
return (
<>
Component 2
>
);
}
function Component3() {
return (
<>
Component 3
>
);
}
function Component4() {
return (
<>
Component 4
>
);
}
function Component5() {
const user = useContext(UserContext);
return (
<>
Component 5
{`Hello ${user} again!`}
>
);
}
export default Component1
Hooks useRef umunnya digunakan untuk mengakses DOM node dalam sebuah komponen. Misal kita mau mengakses element input, maka kita bisa menambahkan ref ke element inputnya.
Perhatikan contoh berikut.
import React, { useRef, useEffect } from "react"
export default function Example() {
const inputRef = useRef()
useEffect(() => {
inputRef.current.value="Anjay"
},[])
return(
)
}
Jika dijalankan value input akan otomatis terisi Anjay.
Hook useCallback dapat digunakan untuk mencegah render child komponen yang tidak di perlukan.
Sebelum memahami useCallback ada baiknya kita memahami React.memo dimana fungsinya yaitu memberikan pengoptimalan terhadap performa React, dimana component hanya akan melakukan render ulang jika props atau state-nya berubah. Contohnya sebagai berikut.
import { useState } from "react";
const App = () => {
console.log('parent render')
const [count, setCount] = useState(0);
const [todos,setTodo] = useState(["todo 1","todo 2"]);
const increment = () => {
setCount((c) => c + 1);
};
return (
<>
Count: {count}
>
);
};
const Todos = ({todos,name}) => {
console.log("child render");
return (
<>
Tugas si {name}
{todos.map((todo, index) => {
return {todo}
;
})}
>
);
};
export default App
Jalankan lalu perhatikan Console browser anda.
Setiap kali tombol + di klik child(Todos) ikut dirender. Bayangkan jika kita memiliki banyak Component dalam 1 page aplikasi, semuanya ikut di render ulang.
Nah.. untuk mengatasi masalah tersebut kita gunakan React.memo untuk melindungi si Component dari render parent dengan cara sebagai berikut.
...
import { memo } from "react";
...
const Todos = memo(({todos,name}) => {
...
});
...
Lalu jalankan kembali.
Dapat dilihat bedanya child tidak dirender ulang.
Kita akan langsung membuat simulasinya kembali kode berikut akan memiliki kemiripan dengan contoh penerapan React.memo sebelumnya.
import { useState, memo } from "react";
const App = () => {
console.log("parent");
const [count, setCount] = useState(0);
const [todos, setTodos] = useState([]);
const increment = () => {
setCount((c) => c + 1);
};
const addTodo = () => {
setTodos((t) => [...t, "New Todo"]);
};
return (<>
Count: {count}
>);
};
const Todos = memo(({ todos, addTodo }) => {
console.log("child render");
return (<>
My Todos
{todos.map((todo, index) => {
return {todo}
;
})}
>);
});
export default App
Lalu jalankan…
Kamu akan melihat bahwa komponen Todos merender ulang meskipun todos tidak berubah.
Mengapa ini tidak berhasil? Padahal sudah menggunakan React.memo, jadi komponen Todos seharusnya tidak dirender ulang karena status todos maupun fungsi addTodo tidak berubah saat hitungan bertambah.
Hal ini karena sesuatu yang disebut Kesetaraan Referensial.
Setiap kali Component merender ulang, fungsinya dibuat ulang. Karena itu, fungsi addTodo sebenarnya telah berubah.
Bagaimana solusinya, disitulah useCallback berperan kita dapat menggunakannya untuk mencegah fungsi dibuat ulang kecuali diperlukan.
import { useState, useCallback } from "react";
...
const addTodo = useCallback(() => {
setTodos((t) => [...t, "New Todo"]);
},[]);
...
Lalu jalankan kembali. Child tidak akan dirender ulang.
Hooks useMemo digunakan untuk mengoptimalkan performance sebuah function. Misal untuk memoize hasil sebuah function. Memoize adalah sebuah teknik yang digunakan mengoptimalkan sebuah program atau istilah kerennya caching.
Dalam contoh berikut, aplikasi memiliki fungsi yang cukup berat yang nantinya akan berjalan pada setiap render. Saat mengubah hitungan atau menambahkan todo, Anda akan melihat delay eksekusi.
import { useState } from "react";
const App = () => {
const [count, setCount] = useState(0);
const [todos, setTodos] = useState([]);
const calculation = expensiveCalculation(count);
const increment = () => {
setCount((c) => c + 1);
};
const addTodo = () => {
setTodos((t) => [...t, "New Todo"]);
};
return (
My Todos
{todos.map((todo, index) => {
return {todo}
;
})}
Count: {count}
Expensive Calculation
{calculation}
);
};
const expensiveCalculation = (num) => {
console.log("Calculating...");
for (let i = 0; i < 1000000000; i++) {
num += 1;
}
console.log("Finish");
return num;
};
export default App
Jalankan lalu perhatikan Console Browser anda setiap anda mengklik tombol Add Todo seharusnya ada jeda beberapa detik.
Tergantung komputer anda kalo teda tidak nampak tambahkan angka 0 lagi dibelakang 1000000000.
Dari kode di atas seharusnya fungsi tidak perlu dirender/dijalankan ulang saat menjalankan tombol Add Todo karena hasilnya akan tetap sama, kecuali anda mengklik tombol +
Namun aturan dari reactjs adalah setiap kali terjadi update state baik todo maupun count, maka Component akan dirender ulang.
Untuk mengatasinya kita bisa menggunakan useMemo untuk mencaching hasil dari function expensiveCalculation.
import { useState, useMemo } from "react";
...
const calculation = useMemo(() => expensiveCalculation(count), [count]);
...
Lalu jalankan kembali.