frhooks v2.2.4-1
FRHooks React Js
Hook untuk membantu CRUD
Installation
Install with npm
npm install frhooks
Install with Yarn
yarn add frhooks
required:
- yup
- axios
Hooks
- HookProvider
- apiRoute
- useMutation
- useValidation
- useServerValidation
- useTable
- useFetch
- useDispatch
- useSelector
- useLang
- useHooks
ApiRoute
apiRoute()\ .headers({...headers})\ - set header\ .params({...params})\ -set params url\ .get(resp => resp, {...config})\ -request GET\ .destroy(resp => resp, {...config})\ -request DELETE\ .data({...data})\ -set data (method POST | PUT)\ .sendJson(method, resp => resp, {...config})\ -mengirim data dalam bentuk json ("application/json")\ .sendUrlEncode(method, resp => resp, {...config})\ -mengirim data dalam bentuk query\ ("application/x-www-form-urlencoded")\ .sendFormData(method, resp => resp, {...config})\ -mengirim data dalam bentuk query ("multipart/form-data")\ .link()\ -generate url
Usage/Example
=> Buat url dalam 1 object\ => apiRoutes.js
const apiRoutes = {
project: {
index: '/project',
detail: '/project/:id'
},
...other
}
export default apiRoutes
=> Jika Menggunakan Typescript\ => Buat Typescript untuk url
declare namespace FRHooks {
type Route = typeof import(".../apiRoutes").default
type ApiRoute = {
[P in keyof Route]: (
path: keyof Route[P],
arg?: Record<string, string>
) => Api;
};
}
=> Daftar Provider\ => Buat instance dari Axios
import { HookProvider } from 'frhooks';
import axios from 'axios';
import apiRoutes from '../apiRoutes'
const api = axios.create({
baseUrl: 'http://localhost:8000/api'
})
<HookProvider client={api} route={apiRoutes}>
<App/>
</HookProvider>
=> Cara Menggunakan ApiRoute\ => Buat instance dari Axios\ => GET, POST, PUT, DELETE
import React FRHooks from 'react'
import {apiRoute} from 'frhooks'
function App(){
const fetchData = async () => {
data = await apiRoute().project('index').get()
}
const fetchDetail = async (id) => {
data = await apiRoute().project('detail', {id}).get()
}
const postData = async () => {
const data = await apiRoute()
.project('index')
.data({name:'Project A', description: ''})
.sendJson('POST')
}
const destroyData = async () => {
data = await apiRoute().project('detail', {id: 1}).destroy()
}
}
useMutation
Manipulasi Form
Props
Props | Fungsi |
---|---|
defaultValue* | inialisasi nilai awal |
schema | schema validasi attribut menggunakan Yup |
format | memberikan format ketika inputan |
scenario | membagi validasi bedasarkan scenario |
Function you can use
No | Object | Type | Fungsi |
---|---|---|---|
1 | loading | boolean | Indikator saat request GET |
2 | processing | boolean | Indiator saat POST, PUT, DESTROY |
3 | data | T | Data |
4 | errors | Object | Menampilkan error saat validasi |
5 | isNewRecord | boolean | Inditator untuk data baru |
6 | setData(value) | function | Fungsi untuk set data |
7 | clearData(except:[]) | function | Membersihkan data tambahkan key jika ingin mengeluarkan data yang tidak ingin di bersihkan |
8 | increment(value) | function | Fungsi untuk manaikan nilai |
9 | decremet(value) | function | Fungsi untuk menurunkan nilai |
10 | reformat(cb(value)) | function | Reformat data |
11 | validate(key, scenario) | boolean | Mendapatkan validasi berdasarkan key |
12 | fails(scenario) | function | Melakukan validasi manual |
13 | setError({...error}) | function | Set manual error |
14 | clearError() | function | Membersihkan Error validasi |
15 | error(key) | function | Mendapatkan Error berdasarkan key |
16 | message(key) | string | Mendapatkan pesan error berdasarkan key |
17 | isValid() | function | Indikator untuk melihat validasi valid |
18 | merge(values) | function | Menggabungkan data |
19 | register(key, defaultValue, options) | function | Mendaftarkan Attribute input |
20 | post | function | Aksi POST |
21 | put | function | Aksi PUT |
22 | destroy | function | Aksi DELETE |
23 | get | function | Aksi GET |
24 | cancel() | function | Membatalkan request axios |
25 | addItem(Key, {value}, position) | function | Menambahkan value baru kedalam array |
26 | setItem(value) | function | Mengubah nilai berdasarkan key |
27 | getItem(Key, defaultValue) | function | Mendapatkan nilai berdasarkan key |
28 | removeItem(key, index) | function | Menghapus value dari array berdasarkan index |
29 | itemValid | boolean | |
30 | setDispatch() | function | |
31 | validateItem(key) | boolean | Mendapatkan validasi array berdasarkan index dan field |
32 | attributes | array | Mendapatkan attribute atau field yand telah daftarkan |
33 | incrementItem(value) | function | Fungsi untuk manaikan nilai |
34 | decrementItem(value) | function | Fungsi untuk menurunkan nilai |
Usage/Example
// app.js
import React from 'react'
import {useMutation, useSelector} from 'frhooks'
const App = () => {
const form = useMutation({
defaultValue: {
id: 0,
title: "",
body: "",
items:[]
},
// Optional validasi
schema: (yup: any) =>
yup.object().shape({
title: yup.string().required().label("Title"),
body: yup.string().required().label("Description"),
//Contoh Array
items:yup.array().of(
y.object().shape({
label: y.string().required().label("Label"),
})
)
.required()
}),
// Optional kondisi
isNewRecord: (data) => data.id === 0,
// Optional Scenario
// Memecah field saat validasi berdasarkan scenatio
scenario: {
create: ["title"],
update: ["title", "body"],
step1: ["title"],
step2: ["items"]
},
// Optional Format
// Optional format saat input
format: {
title: (value) => value.trim(),
},
// Optional Tambah Key unik untuk mendaftarkan ke daftar CONTEXT
key: 'key_context'
});
// Contoh mengirim data POST | PUT
const onSubmit = () => {
// Note: ['/example/:id', {id}] gunakan ini jika butuh nilai
form.post('/example', {
// Optional default: post
// Note: form.put(url, options) jika ingin menggunakan PUT
method: "post",
// Optional validasi, default false
// Note: Pastikan schema telah ditambahkan
validation: true,
// Optional scenario, default: false
// Note: Pastikan scenario telah ditambahkan
scenario: "create",
// Optional send post tanpa data, default: false
useEmpty: false,
// Optional send post tanpa data yang di filter
except: [],
// Optional send post hanya data yang di filter
only: [],
onBeforeSend: () => {
console.log('action before send')
},
onSuccess: (data, jhqx) => {
console.log('action on success', data)
},
onError:(e) => {
console.log('error', e)
},
onAlways: () => {
console.log('action on always')
},
options: {
headers: {
//default; application/json
//Note: Ubah bagian ini jika ingin mengirim data menggunakan Form Data, useMutation akan mengubah secara otomatis object => form-data 'content-type': 'multipart/form-data',
//Note: Ubah bagian ini jika ingin mengirim data menggunakan urlencode, useMutation akan mengubah secara otomatis object => query url encode 'content-type': "application/x-www-form-urlencoded",
...(other options axios config)
}
},
...(other options)
})
}
// Contoh Delete
const onDelete = () => {
// Note: ['/example/:id', {id}] gunakan ini jika butuh nilai
form.destroy('/example', {
onSuccess: (data, jhqx) => {
console.log('action on success', data)
},
...(other options)
})
}
// Contoh GET
const get = () => {
// Note: ['/example/:id', {id}] gunakan ini jika butuh nilai
form.get('/example', {
onSuccess: (data, jhqx) => {
console.log('action on success', data)
},
...(other options)
})
}
const change={(e) => {
form.setData({title: e.target.value})
}
//Membuat validasi saat blur
cost blur={() => {
form.validate('title')
}
//Contoh Manual Validasi
const validation = async () => {
//Normal
const invalid = await form.fails();
//Dengan scenario
const invalid = await form.fails('step1')
//Dengan Schema
const invalid = await form.fails((yup) => yup.object().shape({...schema}))
if(invalid) {
console.log(form.errors)
}
}
//Contoh Manual Validasi Array
const validationArray = async () => {
//Normal
const invalid = await form.validateItem('items');
if(invalid) {
console.log(form.errors)
}
}
const addNew = () => {
form.addItem('items', {label: ''}, 'start' | 'end'| number of index)
}
//Note: Hapus Array
const removeItem = (i) => () => {
form.removeItem('items')
//atau
form.removeItem('items', i)
//atau
form.removeItem('items', (v) v.label === 'test')
}
render <div>
{form.loading ? "Memuat Data..." : JSON.stringify(mutation.data)}
<div>
<input value={form.data.title} onChange={change} onBlur={blur}/>
//Atau
<input {...form.register('name',"", {...options})}/>
{form.error('title') ? <span>{form.message('title')}</span> : null}
</div>
<button onClick={validation} >validasi</button>
<button disabled={!form.isValid()} onClick={onSubmit}>
{form.processing ? "loading..." : "simpan"}
</button>
</div>
}
=> Jika Array
const App = () => {
...(form)
return <div>
<ul>
{
form.data.items.map((value, i) => (
<li key={i}>
<input
value={form.getItem('items.0.label', '')}
onChange={(e) => {
form.setItem( {['items.0.label']: e.target.value})
}}
onBlur={() => {
form.validateItem('items.0.label')
}}
/>
{form.error('items.0.label') ? <span>{form.message('items.0.label')}</span> : null}
<button onClick={removeItem(i)}>- Remove Array</button>
</li>
)
)}
</ul>
<button onClick={validationArray} >validasi array</button>
<button onClick={addNew}> + Add New Array</button>
</div>
}
=> Jika Nested Array dan Seterusnya
const App = () => {
...(form)
return <div>
<ul>
{
form.data.items.map((value, i) => value.items2.map((value2, i2) => (
<li key={i}>
<input
value={form.getItem(`items.${i}.items2.${i2}.label`, '')}
onChange={(e) => {
form.setItem( {[`items.${i}.items2.${i2}.label`]: e.target.value})
}}
onBlur={() => {
form.validateItem(`items.${i}.items2.${i2}.label`)
}}
/>
{form.error(`items.${i}.items2.${i2}.label`) ? <span>{form.message(`items.${i}.items2.${i2}.label`)}</span> : null}
<button onClick={() => {
form.removeItem(`items.${i}.items2`, i2)
}}>- Remove Array</button>
</li>
))
)
}
</ul>
<button onClick={() => {
form.validateItem(`items.${i}.items2`)
}} >validasi array</button>
<button onClick={() => {
form.addItem(`items.${i}.items2`, {label: ''})
}}> + Add New Array</button>
</div>
}
useValidation
Menggunakan validasi schema (Yup)
Props
Props | Fungsi |
---|---|
schema* | schema validasi attribut menggunakan Yup |
scenario | membagi validasi bedasarkan scenario |
value | Data |
Function you can use
No | Props | Type | Fungsi |
---|---|---|---|
1 | errors | object | Hasil validasi |
2 | scenario | string | Mendapatkan scenario |
3 | setData({}) | function | set data |
4 | setError({}) | function | set error manual |
5 | fails({scenario, value}) | function | Melakukan validasi |
6 | validate(field, scenario) | boolean | Melakukan validasi per field |
7 | clearError() | function | Menghapus error |
8 | error(fields) | boolean | Mendapatkan indikasi error per field |
9 | message(fields) | boolean | Mendapatkan pesan error per field |
10 | valid | boolean | Mendapatkan indikasi error |
11 | validateItem(key, attr, index, scenario) | boolean | Melakukan validasi item array |
12 | errorItem(key, attr, index) | boolean | Mendapatkan indikasi error item array |
13 | messageItem(key, attr, index) | string | Mendapatkan pesan error item array |
Usage/Example
// app.js
import React from 'react'
import {useValidation} from 'frhooks'
const App = () => {
const form = useValidation({
// Optional
// value tambahkan value disini untuk validasi bersarkan perubahan data
// form.setData(): jika value ditambahkan maka pada fungsi ini bisa untuk tidak digunakan
value: data,
schema: (yup: any) =>
yup.object().shape({
title: yup.string().required().label("Title"),
body: yup.string().required().label("Description"),
items: y
.array()
.of(
y.object().shape({
text: y.string().required().label("test"),
})
)
.required(),
}),
// Optional Scenario
// Memecah field saat validasi berdasarkan scenatio
scenario: {
create: ["title"],
update: ["body"],
//Experimental jika ingin memvalidasi hanya array saja
//example: form.fails({scenario: "items"})
validationItems: ["items"]
},
});
const validation = async () => {
//Normal
const invalid = await form.fails();
//Dengan scenario
const invalid = await form.fails({scenario: "create"})
//Dengan value
const invalid = await form.fails({value: {...(new value)})
if(invalid) {
console.log(form.errors)
}
}
return "Contoh sama dengan useMutation bukan Array"
}
=> Jika Array
<ul>
{array.map((v, i) => ( <div key={i}>
<input onBlur={() => form.validateItem('items', 'text', i)} />
{form.errorItem('items', 'text', i) ? <span>{form.messageItem('items', 'text', i)}</span> : null}
</div>)}
</ul>
useServerValidation
Menggunakan validasi asyncronus API
Props
Props | Fungsi | |
---|---|---|
url | Alamat api yang dituju | |
selector:(resp) => resp | Mendapatkan data error dengan normal response < 400 Http Code | |
options: {key:(param, locale)} | Mengatur object error | |
param: {type, path} | Mendapatkan object error | |
field | object | Memberi pengaturan invidividual |
callback(err) | Mendpatkan balikan hasil error |
Function you can use
No | Props | Type | Fungsi |
---|---|---|---|
1 | processing | boolean | Mendapatkan indikasi proses |
2 | errors | object | Mendapatkan error |
3 | serve({url, key, only, method, data, cb}) | function | Melakukan validasi |
4 | loading | boolen | Mendapatkan indikasi proses |
5 | validate(key, data, options) | boolean | Melakukan validasi berdasarkan key |
Usage/Example
=> Contoh Error Response Api
//validation.json
error: [
{path: "title", type: "required"},
{path: "phoneNumber", type: 'exist'},
{path: "body", type:"minLength", length: 8}
]
atau
// path dan type diubah menjadi field dan rule
error: [
{field: "title", rule: "required"},
....
]
atau
error:{
code: 5,
name: "is exist"
}
// app.js
import React from 'react'
import {useServerValidation} from 'frhooks'
const App = () => {
const {server, errors} = useServerValidation({
url: "http://localhost/validation",
// Mendapatkan error dari API
selector: (resp) => resp.error,
option: {
//Note: Normal
required: ({path}) => `${path} is required`,
//Note: with locale
required: ({path}, {r, t}) =>r("required", { path: t(path) }, "validation"),
exist: ({path}) => `${path} already exist`,
minLength:({path, length}) => `${path} minimum length is ${length}`,
//Note: jika param diubah
required: ({field}) => `${path} is required`,
},
// Optional
// dapat diubah
param:{
path: "path",// default path,
type: "type",// default type
}
field: {
name: {
url: "exmple.json",
selector: (resp) => {
// Balikan berupa string˝
return resp.data.error.name
}
}
},
// Optional
calback: (err) => {
form.setError(err)
}
});
const validation = async () => {
const valid = await serve({method: "post", ...(other optional options)})
if(!valid){
console.log(errors)
}
}
//Note: Kombinasi dengan useMutation
const onSubmit = () => {
form.post('/example', {
// Optional validasi, default false
validation: true,
serverValidation: {
serve: serve,
method: "post",
},
...(other options)
})
}
return <>{JSON.stringify(errors)}<>
}
useTable
Manipulasi Table
Props
Props | Fungsi |
---|---|
selector* | Mendapatkan data dari respon API |
total* | Mendapatkan jumlah data dari respon API |
disabledOnDidMount | Mematikan aksi saat didmount |
config | Konfigurasi AxiosRequestConfig |
sort | urutan |
pagination | paginasi |
key | Menambahkan data kedaftar CONTEXT |
Function you can use
No | Object | Type | Fungsi |
---|---|---|---|
1 | loading | boolean | Indikator loading saat GET |
2 | total | number | Menampilkan total |
3 | data | T | Data |
4 | orderBy | string | Menampilkan key urutan |
5 | order | asd - desc | Menampilkan type urutan |
6 | query(key, defaultValue) | function | Mendapatkan hasil set query |
7 | setTotal(value) | function | Set total secara manual |
8 | setQuery({value}) | function | Set query |
9 | onOrder(key) | function | Sorting berdasarkan key |
10 | clear() | function | Membersihkan query |
11 | clearExcept([]) | function | Membersihkan query dengan parameter |
12 | clearOnly([]) | function | Membersihkan query dengan parameter |
13 | remove() | function | Membersihkan Error validasi |
14 | reload() | function | Memuat ulang |
15 | remove(key, resetPage) | function | Menghapus query berdasarkan key dan reset page = defaultPage |
16 | add(value, "start" or "end" or number) | function | Menambahkan data baru kedalam list |
17 | update(index or (v) => boolean, value) | function | Memperbaharui data list berdasarkan Index |
18 | destroy(index or (v) => boolean) | function | Menghapus data darri list berdasarlkan Index |
19 | isEmpty | boolean | Mendapatkan indikasi data kosong |
20 | has(key) | boolean | Mendapatkan inidikasi dari key query |
21 | setDispatch() | function | (key: 'list_test') diset untuk mendaftarkan data kedalam context |
22 | pagination | Object | ... |
23 | register() | function | ... |
Pagination Function you can use
Object | Type | Fungsi |
---|---|---|
page | number | Mendapatkan page |
from | number | Mendapatkan nomor urutan pertama |
to | number | Mendapatkan nomor urutan terakhir |
lastPage | number | Mendapatkan nomor page terakhir |
perPageOptions | number[] | Mendapatkan daftar size page tersedia |
perPage | number | Mendapatkan nilai size page |
setPage(value) | function | Set page manual |
setPerPage(value) | function | Set size page manual |
nextButton() | function | ... |
backButton() | function | ... |
firstButton() | function | ... |
lastButton() | function | ... |
onPerPageChange | function | fungsi untuk set nilai size page |
text | string | Mendapatkan summary data |
Usage/Examples
// list.json
//exmple API response
{
status: 200,
data: [...],
total: 10
}
// app.js
import React from 'react'
import {useTable} from 'frhooks'
const App = () => {
//Note: ["/examples/:path", {path: "test"}] bila ingin menambahkan path
const table = useTable("/examples", {
// Mendapatkan data dari response API
selector: (resp) => resp.data,
// Mendapatkan nilai total dari response API
total: (resp) => resp.total,
// Optional
// Note: Cara merubah params sorting
// Example: localhost/example?order=asc&orderby=id
sort: {
params: {
order: "order",
orderBy: "orderBy",
},
order: "desc", // Note: default order, default: desc
orderBy: "id", // Note: default orderBy, default: id
},
// Optional
// Note: Melakukan custome terhadap pagination
pagination: {
//Example: localhost/example?page=1&perPage=10
params: {
page: "page",
perPage: "perPage",
},
startPage: 1,// default page, default: 1 or 0
perPage: 10,// default perPage, default: 10,
perPageOptions: [5, 10, 15, 25],
// formula mendapatkan nilai from
from: (total, page, size, df) => page - 1 + (df === 0 ? 1 : 0)) * size +
(total === 0 ? 0 : df === 0 ? 1 : df),
// formula mendapatkan nilai to
to: (total, page, size, df) => Math.min(total, (page + (df === 0 ? 1 : 0)) * size),
//Mendapatkan nilai page terakhir
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,
},
// Optional mendaftarkan hasil ke CONTEXT
key: 'key_context',
//tambahkan true jika tidak ingin menjalan saat load page, default: false
disabledOnDidMount: false
})
render <div>
<div>
<input type="text" value={table.query('title', '')} onChange={e => table.setQuery({title: e.target.value})} />
//atau
<input type="text" {...table.register("title", "")} />
{table.pagination.text}
<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>
}
useFetch
fetching data
Props
Props | Fungsi |
---|---|
selector* | Mendapatkan data dari respon API |
defaultValue | Nilai default untuk data |
defaultParams | Nila default untuk query |
disabledOnDidMount | Mematikan aksi saat didmount |
config | Konfigurasi AxiosRequestConfig |
debounceTime | Nilau debounce saat setQuery |
deps | Depedencies |
getData(data) | Mendapatkan Data secara manual |
key | Menambahkan data kedaftar CONTEXT |
Function you can use
No | Object | Type | Fungsi |
---|---|---|---|
1 | loading | boolean | Indikator loading saat GET |
2 | total | number | Menampilkan total |
3 | data | T | Data |
4 | error | object | error query |
5 | getQuery(key, defaultValue) | function | Mendapatkan hasil set query |
6 | setQuery({value}) | function | Set query |
7 | clear({except, only}) | function | Membersihkan query |
14 | refresh() | function | Memuat ulang |
16 | add(value, "start" or "end" or number) | function | Menambahkan data baru kedalam list (jika data dalam bentuk array) |
17 | update(index or(v) => number, value) | function | Memperbaharui data list berdasarkan Index (jika data dalam bentuk array) |
18 | destroy(index or (v) => number) | function | Menghapus data dari list berdasarkan Index (jika data dalam bentuk array) |
19 | isEmpty | boolean | Mendapatkan indikasi data kosong |
20 | has(key) | boolean | Mendapatkan indikasi dari key query |
21 | setDispatch() | function | (key: 'list_test') diset untuk mendaftarkan data kedalam context |
Usage/Examples
// list.json
//exmple API response
{
status: 200,
data: [...],
}
// atau
{
status: 200,
data: {...},
}
// app.js
import React from 'react'
import {useFetch} from 'frhooks'
const App = () => {
//Note: ["/examples/:path", {path: "test"}] bila ingin menambahkan path
const project = useFetch("/examples", {
// Mendapatkan data dari response API
selector: (resp) => resp.data,
// Mendapatkan nilai total dari respon API
// Tentukan nilai awal jika array maka [] atau {}
defaultValue: {},
// Optional
// Optional mendaftarkan hasil ke CONTEXT
key: 'key_context',
// Optional
// Tambahkan true jika tidak ingin menjalan saat load page, default: false
disabledOnDidMount: false ,
// Optional
// Jika ingin mendaptkan data secara manual
getData: (value) => {
console.log(value, 'data in here')
}
...(other options)
})
render "Lebih kurang mirip useTable"
}
useDispatch
useSelector
context
Function you can use
Object | Type | Fungsi |
---|---|---|
dispatch(key, value) | function | set data object atau list berdasarkan key |
clearMutation('key') | function | Bersihkan mutasi |
clearList('key') | function | Bersihkan list |
Usage/Examples
=> Jika menggunakan Typescript maka tambahkan ini
//index.d.ts override
declare namespace FRHooks {
type DataContext = {
user: {
name: string;
};
};
}
// app.js
import React from 'react'
import {useDispatch, useSelector} from 'frhooks'
const App = () => {
const {dispatch, clearMutation, clearList} = useDispatch()
// atau
const {dispatch} = useDispatch('key', {
// Optional, default mutation
// Note: Jika array maka ubah menjadi "list"
type: 'mutation',
// Optional hanya untuk bertipe list
total: 0,
defaultValue: {
name: ''
}
})
const result = useSelector(['key'])
// atau modifikasi respon
const result = useSelector(['key'], (data) => data)
React.useEffect(() =>{
dispatch('key', {name: 'test'})
}, [])
render <div>
{JSON.stringify(result)}
</div>
}
useLang
Multi Bahasa
Function you can use
Object | Type | Fungsi |
---|---|---|
t() | function | Mendapatkan hasil terjemah bahasa |
r() | function | Memberi nilai berdasarkan param |
setLang() | function | Menentukan bahasa digunakan |
Usage/Examples
// en.json => pastikan nama file benar "${en}".json
// default json
// ini bisa digunakan untuk memodifikasi pesan validasi useMutation
{
"attribute": {
"name": "Name"
},
"message": {
"exampleMessage": "Hello Word",
"exampleReplaceMessage": "Hello :name"
},
"validation": {
"default": ":path is invalid",
"required": ":path is a required field",
"oneOf": ":path must be one of the follwing values: :values",
"notOneOf": ":path must not be one of the following values: \":values\"",
"defined": ":path must be defined",
"stringLength": ":path must be exactly :length characters",
"stringMin": ":path must be at least :min characters",
"stringMax": ":path must be at most :max characters",
"matches": ":path must match the following: \":regex\"",
"email": ":path must be a valid email",
"url": ":path must be a valid URL",
"uuid": ":path must be a valid UUID",
"trim": ":path must be a trimmed string",
"lowercase": ":path must be a lowercase string",
"uppercase": ":path must be a upper case string",
"numberMin": ":path must be greater than or equal to :min",
"numberMax": ":path must be less than or equal to :max",
"lessThan": ":path must be less than :less",
"moreThan": ":path must be greater than :more",
"positive": ":path must be a positive number",
"negative": ":path must be a negative number",
"integer": ":path must be an integer",
"dateMin": ":path field must be later than :min",
"dateMax": ":path field must be at earlier than :max",
"isValue": ":path field must be :value",
"noUnknown": ":path field has unspecified keys: :unknown",
"arrayMin": ":path field must have at least :min items",
"arrayMax": ":path field must have less than or equal to :max items",
"arrayLength": ":path must have :length} items"
}
}
// id.json => pastikan nama file benar "${id}".json
// ini bisa digunakan untuk memodifikasi pesan validasi useMutation
{
"attribute": {
"name": "Nama",
"mandatory": "Wajib"
},
"message": {
"exampleMessage": "Hallo Dunia",
"exampleReplaceMessage": "Hallo :name"
},
"validation": {
"default": ":path tidak valid",
...dll
}
}
//tsconfig
{
"compilerOptions": {
"resolveJsonModule": true,
}
}
// index.d.ts override*
declare namespace FRHooks {
type AttributeKey =
| keyof typeof import("../lang/en.json")["attribute"]
| Array<keyof typeof import("../lang/en.json")["attribute"]>;
type AttributeMessage =
| keyof typeof import("../lang/en.json")["message"]
| Array<keyof typeof import("../lang/en.json")["message"]>;
type Lang = "en" | "id"
}
import { HookProvider } from 'frhooks';
const language = {
lang: 'en',
// folder berisikan file json, en.json, id.json, ...dll
path: './lang/',
fallback: 'en',
// Optional tambah jika ingin memeliki nilai awal
default: {...default},
// Optional
loading: true,
}
// index.js
<HookProvider language={language}>
<App/>
</HookProvider>
// app.js
import React from 'react'
import {useLang} from 'frhooks'
const App = () => {
const {t, r, setLang} = useLang()
React.useEffect(() =>{
setLang('id') // Set Bahasa
}, [])
render <div>
<p>{t('name') || t(['name', 'mandatory'])}</p>
<p>{r('exampleReplaceMessage', {name: 'BUDI'})}</p>
</div>
}
6 months ago
9 months ago
9 months ago
9 months ago
9 months ago
8 months ago
8 months ago
9 months ago
9 months ago
9 months ago
8 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
9 months ago
9 months ago
9 months ago
10 months ago
10 months ago
10 months ago
11 months ago
11 months ago
11 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago