This is a custom hooks react
npm install ezhooks
or
yarn add ezhooks
for service
http request can use axios, fetch, ...etc
Hook form data mutation
Name |
Type |
Description |
defaultValue* |
T |
Default values for the form. |
scenario |
Object |
Divide data in the form of scenarios |
format |
ObjectFunc |
Provides the format value when input |
import useMutation from 'ezhooks/lib/useMutation';
const App = () => {
const form = useMutation({
defaultValue: {
title: '',
contact: {
phone: '',
office: ''
},
item: [],
rating: 0
}
})
...
}
Name |
Type |
Description |
processing |
bool |
Gives an indication of the process in progress. |
form.processing ? "loading...." : <div>...</div>;
Name |
Type |
Description |
scenario |
string |
current scenario. |
console.log("scenario", form.scenario);
Name |
Type |
Description |
data |
func |
Show all data. |
console.log("Data", form.data());
OR with scenario
console.log("Data", form.data("create"));
Name |
Type |
Description |
setData |
func |
Show all data. |
...
return <div>
<input type='text' name='title' onChange={e => form.setData({[e.target.name]: e.target.value})} />
</div>
Nested setData
for nested values we break them down using dots, form.setData({[a.
b.
c...n
]:value})
set value if object nested (object)
...
return <div>
<input type='text' onChange={e => form.setData({'contact.phone': e.target.value})} />
<input type='text' onChange={e => form.setData({'contact.office': e.target.value})} />
</div>
set value value if array object
...
return <div>
<input type='text' onChange={e => form.setData({'item.0.label': e.target.value})} />
<input type='text' onChange={e => form.setData({'item.0.item.1.label': e.target.value})} />
</div>
value(key*
, defaultValue = '')
Name |
Type |
Description |
value |
func |
Get value by key. |
...
return <div>
<input ... value={form.value('title')}/>
<input ... value={form.value('contact.phone')}/>
<input ... value={form.value('item.0.label')}/>
</div>
Nested value
for get values we break them down using dots, form.value('a.
b.
c...n
')
Name |
Type |
Description |
increment |
func |
increase value. |
...
return <div>
<input type='text' onChange={e => form.increment({'rating': 1})} />
</div
Nested Increment
for nested values we break them down using dots, form.increment({[a.
b.
c...n
]:value})
Name |
Type |
Description |
decrement |
func |
decrease value. |
...
return <div>
<input type='text' onChange={e => form.decrease({'rating': 1})} />
</div
Nested Decrement
for nested values we break them down using dots, form.decrease({[a.
b.
c...n
]:value})
add(key*
, value*
, position)
Name |
Type |
Description |
add |
func |
add array value. |
position |
string, number |
start, end ornumber
|
...
form.add('item', {label: ''}) //default position:end
form.add('item', {label: ''}, 1) //position by number:index start by 0
Nested add
for nested values we break them down using dots, form.add(a.
b.
c...n
, value)
Name |
Type |
Description |
remove |
func |
add array value. |
conditionn |
number,func |
number of index data or func(condition) |
...
form.remove('item', 0)
form.remove('item', (item) => item.label === 'test') //condition with function
Nested remove
for nested values we break them down using dots, form.remove(a.
b.
c...n
, index)
Name |
Type |
Description |
reset |
func |
clear value. |
Name |
Type |
Description |
keys |
func |
get key data |
if scenario true
will display all key from scenario then if scenario set string
key from props.scenario will display from prop.scenario with spesifik key and scenario false
will display all key data. default false
Name |
Type |
Description |
setScenario |
func |
set scenario form the list in props.scenario |
...
form.setScenario('create')
Name |
Type |
Description |
service* |
func |
service. |
scenario |
string |
choose a scenario for the data directly. |
onSuccess |
func |
The function callback on success and returns a response. |
onError |
func |
The function calls back on failure and returns a error. |
onAlways |
func |
function calls back same 'finally' on promise |
Name |
Type |
Description |
ctr |
class |
AbortController. |
scenario |
string |
scenario. |
data |
func |
data. |
keys |
func |
keys. |
event.data(...)
If the scenario has been set, it will automatically retrieve data based on the scenario key. If you want to reset it, fill it with the value true
, if no scenario is set, it will return all data.
...
function onSubmit(){
form.send({
service: (event) => fetch('http:example.com', {
method: 'post',
body: JSON.stringify(event.data()),
signal: event.ctr.signal
}),
onSuccess: (resp) => {
},
onError: (err) => {},
onAlways: () => {}
})
}
TS EventProps
// import { EventSend } from 'ezhooks/lib/useMutation' if typescripts
const addExample = async (event: EventSend) => {
return fetch("http:example.com", {
method: "post",
body: JSON.stringify(event.data()),
signal: event.ctr.signal,
}).then((resp) => resp.json());
};
function onSubmit() {
form.send({
service: addExample,
onSuccess: (resp) => {},
onError: (err) => {},
onAlways: () => {},
});
}
the service can use another method request: GET, PUT, POST, DELETE or PATH
with scenario
const form = useMutation({
...
scenario: {
create: ['title'],
update: ['id', 'title']
}
}
...
const addExample = async (event: EventSend) => {
const data = event.data() // or event.data(true) // or event.data('create') // or event.data(event.scenario)
return fetch("http:example.com", {
method: "post",
body: JSON.stringify(data),
signal: event.ctr.signal,
}).then((resp) => resp.json());
};
function onSubmit(){
form.send({
...
scenario: 'create'
})
}
parsing param
...
const param = {
isUpdate: true
}
const addExample = (param) => async (event: EventSend) => {
const data = event.data()
return fetch("http:example.com", {
method: param.isUpdate ? "put" : "post",
body: JSON.stringify(data),
signal: event.ctr.signal,
}).then((resp) => resp.json());
};
function onSubmit(){
form.send({
...
service: addExample(param)
})
}
Hook for get data
Name |
Type |
Description |
service* |
func |
default values for the form. |
selector |
func |
divide data in the form of scenarios |
defaultValue |
T |
default values for the data |
disabledOnDidMount |
bool |
disable call request for first time render |
debounceTime |
number |
delay time request in milliseconds |
deps |
array |
dependcies |
getData |
func |
function callback for get data |
import useFetch from 'ezhooks/lib/useFetch';
const App = () => {
const fetch = useFetch({
service: () => fetch('http://example.com').then(resp => resp.json())
selector: (resp) => resp.products,
defaultValue: [] //or {}
})
...
}
for service can use another service request like fetch, axios ..etc
Name |
Type |
Description |
loading |
bool |
Gives an indication of the process in progress. |
form.loading ? "loading...." : <div>...</div>;
Name |
Type |
Description |
isEmpty |
bool |
Gives an indication of if empty data. |
form.isEmpty ? "Data not available" : <div>...</div>;
Name |
Type |
Description |
data |
T |
value. |
Name |
Type |
Description |
query |
object |
query parameters |
Name |
Type |
Description |
setQuery |
func |
function for set query |
<input
type="search"
name="keywords"
onChange={(e) => fetch.setQuery({ [e.target.name]: fetch.target.value })}
/>
getQuery(key*
, defaultValue = '')
Name |
Type |
Description |
setQuery |
func |
function for set query |
<input type='search' name='keywords' ... value={fecth.getQuery('keywords')}) />
Name |
Type |
Description |
refresh |
func |
recall request |
<button onClick={fetch.refresh}>Reload</button>
clear(fields?: {except, only})
Name |
Type |
Description |
clear |
func |
function for clear all query or some query by key |
<button onClick={ ()=> fetch.clear()}>Reset All</button>
<button onClick={ ()=> fetch.clear({only: ['keywords']})}>Reset only keywords</button>
<button onClick={ ()=> fetch.clear({except: ['keywords']})}>Reset excpet keywords</button>
Name |
Type |
Description |
has |
func |
function for check query key is exists |
if (fetch.has("keywords")) {
console.log("exists");
}
Name |
Type |
Description |
cancel |
func |
cancel request pending |
<button onClick={fetch.cancel}>Cancel</button>
Hook for get request with pagination
Props |
Type |
Description |
service* |
func |
service |
selector* |
func |
function for select data from response API |
total* |
func |
function for select total from response API |
disabledOnDidMount |
bool |
disable for first time render |
replaceUrl |
bool |
include replace url |
sort |
obj |
set object for sort in url |
pagination |
obj |
pagination for data |
Props |
Type |
Description |
loading |
bool |
loading indication |
total |
number |
total |
data |
T |
data |
orderBy |
string |
displays sorting by column |
order |
asc,desc |
displays sort by |
query(?key, ?defaultValue) |
func |
get all parameters or based on key |
setTotal(value* ) |
func |
give the total value manually |
setQuery(value* ) |
func |
set parameter |
onSort(key* ) |
func |
function to sort by key |
clear(?{except, only}) |
func |
function to clear parameters |
remove(?key, ?resetPage) |
func |
remove key parameter and reset page to number |
reload() |
func |
reload |
isEmpty |
bool |
get an empty data indication |
has(key* ) |
bool |
function to check key parameters |
pagination |
obj |
... |
Pagination Props
Props |
Type |
Description |
page |
number |
number of page |
from |
number |
... |
to |
number |
... |
lastPage |
number |
get the page number of the last available page. |
perPageOptions |
number[] |
get the page size options |
perPage |
number |
the number of items to be shown per page |
setPage(value* ) |
func |
set page manual |
setPerPage(value* ) |
func |
set size page manual |
nextButton() |
func |
... |
backButton() |
func |
... |
firstButton() |
func |
... |
lastButton() |
func |
... |
onPerPageChange |
func |
function for size per page |
text |
string |
summary |
// api response
{
"total": 100,
"data" : [...]
}
import useTable from 'ezhooks/lib/useTable'
// import { EventTable } from 'ezhooks/lib/useTable' if typescripts
const getExample = async (event: EventTable) => {
let url = 'http://example.com/products'
const params = new URLSearchParams(event.params)
url += `?${params.toString()}`
const req = await fetch(url, {
signal: event.ctr.signal
})
return await req.json()
}
const App = () => {
const table = useTable({
service: getExample,
selector: (resp) => resp.data,
total: (resp) => resp.total,
// this option for custom sort
sort: {
params: {
order: "order",
orderBy: "orderBy",
},
order: "desc", // Note: default order, default: desc
orderBy: "id", // Note: default orderBy, default: id
},
// this option for custom pagination
pagination: {
params: {
page: "page",
perPage: "perPage",
},
startPage: 1,// default page, default: 1 or 0
perPage: 10,// default perPage, default: 10,
perPageOptions: [5, 10, 15, 25],
from: (total, page, size, df) => page - 1 + (df === 0 ? 1 : 0)) * size +
(total === 0 ? 0 : df === 0 ? 1 : df),
to: (total, page, size, df) => Math.min(total, (page + (df === 0 ? 1 : 0)) * size),
lastPage: (total, size) => Math.max(0, Math.ceil(total / size)), // formula
disableFirst: (total, page, df) => total !== 0 && page === df,
disableLast: (total, page, lp) => total !== 0 && page === lp,
},
});
render <div>
<div>
<input type="text" value={table.query('title', '')} onChange={e => table.setQuery({title: e.target.value})} />
{table.pagination.text} <!-- summary !-->
<button {...table.pagination.firstButton()}>prev</button>
<button {...table.pagination.backButton()}>prev</button>
{table.pagination.page}
<button {...table.pagination.nextButton()}>next</button>
<button {...table.pagination.lastButton()}>next</button>
<button onClick={() => table.onOrder("name")}>
{table.order}-{table.orderBy}
</button>
<button onClick={table.clear}>Clear</button>
<button onClick={table.reload}>Reload</button>
</div>
<table>
<thead>
<tr>
<td>No</td>
<td>Title</td>
</tr>
</thead>
<tbody>
{table.loading ? 'loading...' : null}
{table.data.map((v: any, i) => (
<tr key={i}>
<td>{table.data.from + (i+1)}</td>
<td>{v.title}</td>
</tr>
))}
</tbody>
</table>
</div>
}
additional props array data for manipulation data
Props |
Type |
Description |
add(value* , ?position) |
func, position:end,start,number |
add data, |
update(index or (value) => boolean, value* ) |
func |
update value by index |
destroy(index or (value) => boolean) |
func |
delete data by index |
server validation
Name |
Type |
Description |
service* |
func |
service. |
data* |
object |
data |
message* |
ObjFunc |
function for set message |
param* |
obj |
param field |
//API Response
error: [
{field: "title", type: "required"},
]
or
error: {
field: 'title',
type: 'required
}
import useSValidation from 'ezhooks/lib/useSValidation';
const App = () => {
const server = useSValidation({
service: (event) => {
fetch("http://example/validation", {method: 'post', body: event.data})
.then((resp) => resp.json())
.then((resp) => {
event.parser(resp.error);
});
},
data: {
title: "",
},
message: {
required: (resp) => "this field is required",
},
param: {
path: "field",
type: "type"
}
})
...
}
Name |
Type |
Description |
processing |
bool |
gives an indication of the process in progress. |
server.processing ? "loading...." : <div>...</div>;
Name |
Type |
Description |
error |
bool |
get indication error by all or key. |
...
server.error()
//
server.error('key')
Name |
Type |
Description |
message |
string |
get message |
...
server.message('key')
Name |
Type |
Description |
clear |
func |
clear error. |
Name |
Type |
Description |
cancel |
func |
cancel request pending. |
Name |
Type |
Description |
validate |
func |
check validation. |
...
server.validate()
//or
server.validate({
service: (event) => {
fetch("http://example/validation", {method: 'post', body: event.data})
.then((resp) => resp.json())
.then((resp) => {
event.parser(resp.error);
});
}
})
//or
server.validate({
service: (data) => (event) => {
fetch("http://example/validation", {method: 'post', body:data})
.then((resp) => resp.json())
.then((resp) => {
event.parser(resp.error);
});
}
})