Pada tampilan aplikasi Simple Todo yang sudah kita buat terdapat form di bagian Header. Kita akan memodifikasi komponen Header untuk menambahkan fungsi agar aplikasi kita bisa menambahkan data dari form dan dikirim ataupun disimpan melalui API. Buka kembali file src/components/Header.js dan lakukan perubahan seperti berikut.
src/components/Header.js
import { useState } from "react";
const Header = () => {
const [title, setTitle] = useState("");
// fungsi untuk menambah data todo melalui API ketika tombol "Add" di klik
const addTodo = () => {
const newTodo = {title, done: false}
fetch('http://localhost:8000/todos', {
method: 'POST',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(newTodo)
}).then(() => {
// ketika sukses menambah data, reset form dengan mengeset state title menjadi empty string
setTitle("")
console.log('new todo added.')
});
}
return (
<div id="todo-header" className="header">
<h2>Simple Todo App</h2>
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<span className="add-button" onClick={addTodo}>Add</span>
</div>
);
};
export default Header;
Pada kode di atas kita membuat variabel state lokal bernama title dengan nilai default kosong. Dimana value dari variabel tersebut akan otomatis berubah dengan value yang kita isikan pada form.
const [title, setTitle] = useState("");
Baris selanjutnya kita membuat function addTodo yang berfungsi untuk menambahkan data todo baru dengan mengirimkan data tersebut melalui API dengan bantuan fetch API. Dan ketika data sukses dikirim maka kita mengeset kembali variabel title dengan nilai kosong untuk mereset form.
// fungsi untuk menambah data todo melalui API ketika tombol "Add" di klik
const addTodo = () => {
const newTodo = {title, done: false}
fetch('http://localhost:8000/todos', {
method: 'POST',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(newTodo)
}).then(() => {
// ketika sukses menambah data, reset form dengan mengeset state title menjadi empty string
setTitle("")
console.log('new todo added.')
});
}
Pada bagian render element HTML kita mengeset value input dengan variabel title dan menambahkan event onChange untuk mengubah nilai variabel title. Kita juga menambahkan even onClick untuk memanggil function addTodo pada button "Add".
return (
<div id="todo-header" className="header">
<h2>Simple Todo App</h2>
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<span className="add-button" onClick={addTodo}>Add</span>
</div>
);
Sekarang kamu bisa coba menambahkan data baru dengan mengisi form yang ada. Dan jika berhasil akan muncul alert dengan pesan "new todo added".
Jika diperhatikan masih ada yang kurang. Ketika kita berhasil menambahkan data todo baru. Data tersebut tidak otomatis muncul pada bagian todo list. Kita harus merefresh halaman pada browser dan data tersebut baru bisa muncul. Ini dikarenakan kita tidak bisa mengupdate variabel state yang ada pada komponen TodoList dari komponen lain (Header).
Kita akan menggunakan sedikit trik untuk mengatasi masalah di atas. Kita akan membuat state pada parent component dan membuat function untuk mengupdate dan mengambil value dari state tersebut dari child componentnya. Di sini parent componentnya ada pada file src/App.js maka kita akan menambahkan state dengan nama isRefresh kemudian membuat function setRefresh untuk mengupdate value state tersebut.
src/App.js
import { useState } from "react";
import Header from "./components/Header";
import TodoList from "./components/TodoList";
function App() {
const [isRefresh, setIsRefresh] = useState(true)
const setRefresh = (status) => {
setIsRefresh(status)
}
return (
<div className="App">
<div className="content">
<Header setRefresh={setRefresh} />
<TodoList setRefresh={setRefresh} isRefresh={isRefresh} />
</div>
</div>
);
}
export default App;
Pada kode di atas kita membuat state isRefresh dan function setRefresh dan melemparnya sebagai props pada komponen Header dan TodoList. Hal tersebut agar kita bisa mengupdate state isRefresh yang berada pada komponen App dari komponen lain baik dari Header maupun TodoList.
Pada komponen Header kita akan menangkap function setRefresh sebagai props dan memanggil function tersebut ketika proses menambahkan data API sukses.
src/components/Header.js
import { useState } from "react";
const Header = ({setRefresh}) => {
const [title, setTitle] = useState("");
// fungsi untuk menambah data todo melalui API ketika tombol "Add" di klik
const addTodo = () => {
const newTodo = {title, done: false}
fetch('http://localhost:8000/todos', {
method: 'POST',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(newTodo)
}).then(() => {
// ketika sukses menambah data, reset form dengan mengeset state title menjadi empty string
setTitle("")
setRefresh(true)
setTimeout(() => {
alert('new todo added.')
}, 500)
});
}
return (
<div id="todo-header" className="header">
<h2>Simple Todo App</h2>
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<span className="add-button" onClick={addTodo}>Add</span>
</div>
);
};
export default Header;
Dan pada komponen TodoList kita perlu memodifikasinya juga dengan menangkap props isRefresh dan setRefresh. Pada blok useEffect kita perlu mengubahnya juga yang intinya prose pengambilan data dari API tidak hanya akan dijalankan ketika pertama kali komponen selesa di render tetapi juga ketika value state isRefresh berubah menjadi true.
src/components/TodoList
import { useEffect, useState } from "react";
import TodoItem from "./TodoItem";
const TodoList = ({isRefresh, setRefresh}) => {
const [todos, setTodos] = useState([]);
useEffect(() => {
// memanggil API untuk mengambil data todos
if (isRefresh) {
fetch("http://localhost:8000/todos")
.then((res) => {
return res.json();
})
.then((data) => {
setRefresh(false)
// ketika Rest API sukses, simpan data dari response ke dalam state lokal
setTodos(data);
})
.catch((err) => {
setRefresh(false)
if (err.name === "AbortError") {
console.log("fetch aborted.");
}
});
}
}, [isRefresh, setRefresh]);
return (
<ul id="todo-list">
{todos.map((todo) => (
<TodoItem todo={todo} key={todo.id} />
))}
</ul>
);
};
export default TodoList;
Sekarang kita coba lagi untuk menambahkan data baru. Jika tidak ada kesalahan seharusnya ketika kita mengisi form dan mengklik tombol Add maka otomatis data todo baru akan ditambahkan ke todo list kemudian baru muncul alert pesan "new todo added".
Source Code: