ezhooks

EZHooks v2 - Documentation

Author: Fajar Rizky Hidayat
Version: 2.0


Table of Contents


useFetch

Overview

Props

Return

Selector methods and state

Examples

Basic fetch (URL)

import useFetch from 'ezhooks';

function UserProfile() {
  const { fetch, selector } = useFetch({ map: ['getUser'] });
  const { data, loading, reload } = selector('getUser');

  const handleFetch = () => {
    fetch('getUser', {
      url: '/api/users/1',
      onJson: (resp, cb) => cb(resp.data)
    });
  };

  return (
    <div>
      {loading && <p>Loading...</p>}
      {data && <p>Hello, {data.name}</p>}
      <button onClick={handleFetch}>Fetch User</button>
      <button onClick={reload}>Reload</button>
    </div>
  );
}

Service-based fetch

const userService = (event) => fetch(`/api/users/${event.params.id}`).then(r => r.json());

function UserFetch() {
  const { fetch, selector } = useFetch({ map: ['user'] });
  const { data, loading } = selector('user');

  const load = (id) => {
    fetch('user', {
      service: userService,
      params: { id },
      onSuccess: (resp, cb) => cb(resp.data),
      onError: (e) => console.error(e)
    });
  };

  return <button onClick={() => load(1)}>{loading ? 'Loading' : 'Load'}</button>;
}

Auto-fetch on mount

useFetch({
  map: ['profile'],
  didMount: {
    profile: {
      url: '/api/profile',
      onJson: (resp, cb) => cb(resp.data)
    }
  }
});

useTable

Overview

Props

Return highlights

Examples

Basic table

function UserTable() {
  const table = useTable({
    service: async (event) => {
      const params = new URLSearchParams(event.params);
      return fetch(`/api/users?${params}`).then(r => r.json());
    },
    selector: (resp) => resp.data,
    total: (resp) => resp.total
  });

  return (
    <table>
      <tbody>
        {table.data.map(u => <tr key={u.id}><td>{u.name}</td></tr>)}
      </tbody>
    </table>
  );
}

Sorting

<th onClick={() => table.onSort('name')}>
  Name {table.orderBy === 'name' ? table.order : null}
</th>

Pagination

const { pagination } = table;
<button {...pagination.firstButton()}>First</button>
<button {...pagination.backButton()}>Prev</button>
<span>Page {pagination.page}</span>
<button {...pagination.nextButton()}>Next</button>
<button {...pagination.lastButton()}>Last</button>
<select value={pagination.perPage} onChange={pagination.onPerPageChange}>
  {pagination.perPageOptions.map(o => <option key={o} value={o}>{o}</option>)}
</select>
<p>{pagination.text}</p>

Data manipulation

table.add(newUser, 'start');
table.update(u => u.id === 1, { name: 'Updated' });
table.destroy(u => u.id === 1);

useMutation

Overview

Props

Return highlights

Examples

Basic form

function LoginForm() {
  const form = useMutation({ defaultValue: { email: '', password: '' } });

  const submit = () => {
    form.send({
      service: async (event) => fetch('/api/login', { method: 'POST', body: JSON.stringify(event.data) }).then(r => r.json()),
      onSuccess: (resp) => { localStorage.setItem('token', resp.token); window.location.href = '/dashboard'; },
      onError: (e) => console.error(e)
    });
  };

  return (
    <form onSubmit={(e) => { e.preventDefault(); submit(); }}>
      <input value={form.value('email')} onChange={e => form.setData({ email: e.target.value })} />
      <input value={form.value('password')} onChange={e => form.setData({ password: e.target.value })} />
      <button disabled={form.processing}>{form.processing ? 'Processing...' : 'Login'}</button>
    </form>
  );
}

Array fields

form.add('emails', { id: Date.now(), value: '' }, 'end');
form.remove('emails', idx);
form.upsert('items', newItem, ['id'], 'start');

Increment/decrement

form.increment({ quantity: 1 });
form.decrement({ quantity: 1 });

Common Patterns

Combined CRUD flow

Example flow


Event Object

When passed to service/send functions:


Best Practices