Aplikasimu semakin lama semakin kompleks, tapi tapi kamu tidak tahu bagaimana mengaturnya. State dipassing ke beberapa component terkadang sulit untuk dilacak. Jika itu terjadi padamu, berarti kamu membutuhkan Redux. Dan ini adalah contoh alur state yang rumit.
Redux adalah library Javascript yang dapat membantumu untuk mengatur state secara global. Dapat diintegrasikan dengan framework atau library lain seperti Angular dan React. Ini adalah contoh alur state jika kamu menggunakan Redux.
Yeah, kamu seperti saya. Saya tidak menemukan tutorial Redux yang bagus dan jelas dari internet. Tapi sekarang saya akan menjelaskannya padamu semudah mungkin.
Penjelasan
Redux memiliki tiga bagian utama:
- Action
- Reducer
- Store
Action adalah pengangkut informasi yang mengirimkan data dari aplikasimu kepada store. Action hanya berbentuk javascript object pada umumnya. Dan membutuhkan properti bernama type untuk mengindikasikan hal yang akan terjadi (valuenya bebas) dan properti bernama apapun dan berapapun jumlahnya sesuai data yang akan dikirim ke store.
// Mengandung semua data yang dibutuhkan
// untuk membuat kontak baru
{
type: 'ADD_CONTACT',
contactID: 1,
name: 'Gattigaga Hayyuta Dewa',
phone: '+62 777 777 777'
}
// Mengandung contactID sebagai referensi
// untuk menghapus kontak
{
type: 'REMOVE_CONTACT',
contactID: 1
}
Reducer adalah function yang mendefinisikan bagaimana state aplikasi diubah setelah melakukan dispatch. Nama function akan mejadi nama state nya dan membutuhkan dua argument, state dan action. Argument state wajib memiliki default value dan argument action adalah action yang akan kamu dispatch.
function contacts(state = [], action) {
switch (action.type) {
case "ADD_CONTACT":
const { contactID, name, phone } = action;
return [
...state,
{
contactID,
name,
phone
}
];
default:
return state;
}
}
Store adalah tempat untuk menyimpan state aplikasimu. Hanya satu store saja yang wajib dimiliki dalam aplikasimu.
Praktek
Oke, sekarang waktunya praktek. Kita akan membuat Contact App menggunakan React, dan memiliki fitur seperti menambah dan menghapus kontak. Pertama, buat React project menggunakan create-react-app dari Terminal.
create-react-app learn-redux
Lalu install redux and react-redux.
npm install --save redux react-redux
Buat beberapa Action Creator di src/states/actions.js. Oh ya, aku lupa untuk menjelaskan apa itu Action Creator. Action Creator adalah sebuah function yang menghasilkan action.
// Nilai awal contactID
let currentID = 0;
export function addContact(contact) {
const { name, phone } = contact;
currentID += 1;
return {
type: "ADD_CONTACT",
id: currentID,
name,
phone
};
}
export function removeContact(id) {
return {
type: "REMOVE_CONTACT",
id
};
}
Selanjutnya, buat reducer di src/states/reducers.js.
import { combineReducers } from "redux";
function contacts(state = [], action) {
switch (action.type) {
case "ADD_CONTACT":
// Menambahkan kontak baru kedalam daftar
return [
...state,
{
id: action.id,
name: action.name,
phone: action.phone
}
];
case "REMOVE_CONTACT":
// Menghapus kontak dari daftar
return state.filter(contact => contact.id !== action.id);
default:
return state;
}
}
const Reducers = combineReducers({
contacts
// Reducer lain yang mungkin kamu butuhkan
});
export default Reducers;
Sekarang buat store di src/index.js.
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { createStore } from "redux";
import App from "./App";
import Reducers from "./states/reducers";
// Buat store dari reducer
const store = createStore(Reducers);
ReactDOM.render(
// Buat store ada untuk semua container component
// tanpa mem-passing-nya secara langsung
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
Lalu buat sebuah component sebagai container dari ContactItem di src/components/ContactList.js.
import React from "react";
const ContactList = ({ children }) => (
<div className="ContactList">{children}</div>
);
export default ContactList;
Dan buat component ContactItem itu sendiri di src/components/ContactItem.js.
import React from "react";
const ContactItem = ({ name, phone, onClickDelete }) => (
<div className="ContactItem">
<p className="ContactItem__name">{name}</p>
<p className="ContactItem__phone">{phone}</p>
<button
type="button"
className="ContactItem__button"
onClick={onClickDelete}
>
Delete
</button>
</div>
);
export default ContactItem;
Lalu kita memasukan fungsional nya di src/App.js.
import React, { Component } from "react";
import { connect } from "react-redux";
import ContactList from "./components/ContactList";
import ContactItem from "./components/ContactItem";
import { addContact, removeContact } from "./states/actions";
class App extends Component {
constructor(props) {
super(props);
this.state = {
name: "",
phone: ""
};
}
render() {
const { name, phone } = this.state;
const { contacts, addNewContact, removeExistingContact } = this.props;
return (
<div className="App">
<div className="App__form">
<input
type="text"
value={name}
onChange={event => this.setState({ name: event.target.value })}
className="App__input"
placeholder="Name"
/>
<br />
<input
type="text"
value={phone}
onChange={event => this.setState({ phone: event.target.value })}
className="App__input"
placeholder="Phone"
/>
<br />
<button
type="button"
onClick={() => {
if (!name || !phone) {
alert("Field cannot be empty !");
return;
}
this.setState({ name: "", phone: "" });
addNewContact({ name, phone });
}}
className="App__button"
>
Add New Contact
</button>
</div>
<ContactList>
{contacts.map(contact => {
return (
<ContactItem
key={contact.id}
name={contact.name}
phone={contact.phone}
onClickDelete={() => removeExistingContact(contact.id)}
/>
);
})}
</ContactList>
</div>
);
}
}
// Mengambil state dari store dan mempassing nya
// kedalam component App sebagai props
const mapStateToProps = ({ contacts }) => ({
contacts
});
// Membuat fungsional yang membutuhkan fungsi dispatch
const mapDispatchToProps = dispatch => ({
addNewContact: contact => {
dispatch(addContact(contact));
},
removeExistingContact: contactID => {
dispatch(removeContact(contactID));
}
});
export default connect(mapStateToProps, mapDispatchToProps)(App);
Inilah hasilnya. Kamu berhasil membuat aplikasi Kontak dengan beberapa fitur sederhana.
Kesimpulan
Aplikasi yang lebih besar pada umumnya memiliki state yang lebih rumit dan sulit untuk diatur. Tapi dengan Redux, kamu dapat membuat aplikasi dengan state yang lebih mudah diatur. Kamu dapat mengatur state aplikasi secara global. Maka dari itu, jangan ragu untuk menggunakan Redux jika state aplikasimu dirasa sudah mulai kompleks dan susah untuk diatur. Akhir kata, kamu dapat meng-clone contoh kode dengan tambahan style dari repo ini.
Cheers !