Skip to content
This repository was archived by the owner on Jan 14, 2021. It is now read-only.

Commit 823ca93

Browse files
authored
Merge pull request #10 from react-hook-form/feature/support-better-with-native
Feature/support better with native
2 parents 7f98dd5 + 2391032 commit 823ca93

3 files changed

Lines changed: 128 additions & 64 deletions

File tree

README.md

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,12 @@
4141

4242
## Demo
4343

44-
Check out this <a href="https://codesandbox.io/s/react-hook-form-hookforminput-rzu9s">demo</a>.
44+
Check out this <a href="https://codesandbox.io/s/react-hook-form-hookforminput-rzu9s">React Web demo</a> or <a href="https://snack.expo.io/@bluebill1049/test-react-hook-form-input">React Native demo</a>.
4545

4646
## Quickstart
4747

48+
#### React Web
49+
4850
```jsx
4951
import React from 'react';
5052
import useForm from 'react-hook-form';
@@ -54,7 +56,6 @@ import Select from 'react-select';
5456
const options = [
5557
{ value: 'chocolate', label: 'Chocolate' },
5658
{ value: 'strawberry', label: 'Strawberry' },
57-
{ value: 'vanilla', label: 'Vanilla' },
5859
];
5960

6061
function App() {
@@ -69,14 +70,7 @@ function App() {
6970
register={register}
7071
setValue={setValue}
7172
/>
72-
<button
73-
type="button"
74-
onClick={() => {
75-
reset({
76-
reactSelect: '',
77-
});
78-
}}
79-
>
73+
<button type="button">
8074
Reset Form
8175
</button>
8276
<button>submit</button>
@@ -85,19 +79,58 @@ function App() {
8579
}
8680
```
8781

82+
#### React Native
83+
84+
```jsx
85+
import * as React from 'react';
86+
import { View, TextInput, Button } from 'react-native';
87+
import useForm from 'react-hook-form';
88+
import { RHFInput } from './index';
89+
90+
export default () => {
91+
const { register, setValue, handleSubmit } = useForm();
92+
const onSubmit = data => console.log(data);
93+
94+
const onChange = args => ({
95+
value: args[0].nativeEvent.text,
96+
});
97+
98+
return (
99+
<View style={styles.container}>
100+
<RHFInput
101+
register={register}
102+
setValue={setValue}
103+
as={<TextInput />}
104+
onChangeEvent={onChange}
105+
name="firstName"
106+
/>
107+
108+
<Button
109+
title="Button"
110+
onPress={handleSubmit(onSubmit)}
111+
/>
112+
</View>
113+
);
114+
};
115+
```
116+
88117
## API
89118

90-
| Prop | Type | Required | Default | Description |
91-
| :----------- | :-------- | :------: | :---------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
92-
| `as` | Component || | Component reference eg: `Select` from `react-select` |
93-
| `name` | string || | Unique name to register the custom input |
94-
| `setValue` | Function | | | (optional when using <a href="https://react-hook-form.com/api#FormContext">FormContext</a>) React Hook Form <a href="https://react-hook-form.com/api#setValue">setValue</a> function |
95-
| `register` | Function | | | (optional when using <a href="https://react-hook-form.com/api#FormContext">FormContext</a>) React Hook Form <a href="https://react-hook-form.com/api#register">register</a> function |
96-
| `unregister` | Function | | | (optional when using <a href="https://react-hook-form.com/api#FormContext">FormContext</a>) React Hook Form <a href="https://react-hook-form.com/api#unregister">unregister</a> function |
97-
| `mode` | string | | `onSubmit` | <a href="https://react-hook-form.com/api#useForm">Mode</a> option for triggering validation |
98-
| `rules` | Object | | `undefined` | Validation rules according to <a href="https://react-hook-form.com/api#register">register</a> at React Hook Form |
99-
| `type` | string | | `input` | Currently support `checkbox` or `input` input type includes: `radio` and `select` |
100-
| `...rest` | Object | | | Any props assigned will be pass through to your Input component |
119+
| Prop | Type | Required | Default | Description |
120+
| :-------------- | :-------- | :------: | :---------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
121+
| `as` | Component || | Component reference eg: `Select` from `react-select` |
122+
| `name` | string || | Unique name to register the custom input |
123+
| `setValue` | Function | | | (optional when using <a href="https://react-hook-form.com/api#FormContext">FormContext</a>) React Hook Form <a href="https://react-hook-form.com/api#setValue">setValue</a> function |
124+
| `register` | Function | | | (optional when using <a href="https://react-hook-form.com/api#FormContext">FormContext</a>) React Hook Form <a href="https://react-hook-form.com/api#register">register</a> function |
125+
| `unregister` | Function | | | (optional when using <a href="https://react-hook-form.com/api#FormContext">FormContext</a>) React Hook Form <a href="https://react-hook-form.com/api#unregister">unregister</a> function |
126+
| `mode` | string | | `onSubmit` | <a href="https://react-hook-form.com/api#useForm">Mode</a> option for triggering validation |
127+
| `rules` | Object | | `undefined` | Validation rules according to <a href="https://react-hook-form.com/api#register">register</a> at React Hook Form |
128+
| `type` | string | | `input` | Currently support `checkbox` or `input` input type includes: `radio` and `select` |
129+
| `onChangeName` | string | | | This prop allow you to target that specific event name, eg: when `onChange` event is named `onTextChange` |
130+
| `onChangeEvent` | Function | | | Callback function to return `value` or `checked`. event callback argument may have different signature and this props allow you to customise the value return. |
131+
| `onBlurName` | string | | | This prop allow you to target that specific event name, eg: when `onBlur` event is named `onTextBlur` |
132+
| `onBlurEvent` | Function | | | Callback function to return `value` or `checked`. event callback argument may have different signature and this props allow you to customise the value return. |
133+
| `...rest` | Object | | | Any props assigned will be pass through to your Input component |
101134

102135
## Contributors
103136

src/index.tsx

Lines changed: 25 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,9 @@
11
import * as React from 'react';
22
import { useFormContext } from 'react-hook-form';
3+
import { Props, EventFunction } from './types';
34

4-
export type ValidateResult = string | boolean | undefined;
5-
6-
export type Validate = (data: any) => ValidateResult;
7-
8-
type ValidationOptionObject<Value> = Value | { value: Value; message: string };
9-
10-
type ValidationOptions = Partial<{
11-
required: boolean | string;
12-
min: ValidationOptionObject<number | string>;
13-
max: ValidationOptionObject<number | string>;
14-
maxLength: ValidationOptionObject<number | string>;
15-
minLength: ValidationOptionObject<number | string>;
16-
pattern: ValidationOptionObject<RegExp>;
17-
validate:
18-
| Validate
19-
| Record<string, Validate>
20-
| { value: Validate | Record<string, Validate>; message: string };
21-
}>;
22-
23-
type Props = {
24-
setValue: (name: string, value: any, trigger?: boolean) => void;
25-
register: (ref: any, rules: ValidationOptions) => (name: string) => void;
26-
unregister?: (name: string) => void;
27-
name: string;
28-
as: React.ReactElement<any>;
29-
type?: string;
30-
rules?: ValidationOptions;
31-
value?: string | boolean;
32-
onChange?: (value: any) => void;
33-
onBlur?: (value: any) => void;
34-
mode?: 'onBlur' | 'onChange' | 'onSubmit';
35-
defaultValue?: string;
36-
defaultChecked?: boolean;
37-
};
38-
39-
function getValue(e: any, { isCheckbox }: { isCheckbox: boolean }) {
40-
return e && e.target ? (isCheckbox ? e.target.checked : e.target.value) : e;
5+
function getValue(target: any, { isCheckbox }: { isCheckbox: boolean }) {
6+
return target ? (isCheckbox ? target.checked : target.value) : target;
417
}
428

439
const RHFInput = React.memo(
@@ -55,6 +21,10 @@ const RHFInput = React.memo(
5521
value,
5622
defaultValue,
5723
defaultChecked,
24+
onChangeName,
25+
onChangeEvent,
26+
onBlurName,
27+
onBlurEvent,
5828
...rest
5929
}: Props) => {
6030
const isCheckbox = type === 'checkbox';
@@ -74,23 +44,29 @@ const RHFInput = React.memo(
7444
const register = methods ? methods.register : registerFromProp;
7545
const unregister = methods ? methods.unregister : unregisterFromProp;
7646

77-
const commonTask = (e: any) => {
78-
const data = getValue(e, { isCheckbox });
47+
const commonTask = (target: any) => {
48+
const data = getValue(target, { isCheckbox });
7949
setInputValue(data);
8050
valueRef.current = data;
8151
return data;
8252
};
8353

54+
const eventWrapper = (event: EventFunction) => {
55+
return (...arg: any) => {
56+
commonTask(event(arg));
57+
};
58+
};
59+
8460
const handleChange = (e: any) => {
85-
const data = commonTask(e);
61+
const data = commonTask(e ? e.target : e);
8662
setValue(name, data, isOnChange);
8763
if (onChange) {
8864
onChange(e);
8965
}
9066
};
9167

9268
const handleBlur = (e: any) => {
93-
const data = commonTask(e);
69+
const data = commonTask(e ? e.target : e);
9470
setValue(name, data, isOnBlur);
9571
if (onBlur) {
9672
onBlur(e);
@@ -126,8 +102,14 @@ const RHFInput = React.memo(
126102

127103
return React.cloneElement(as, {
128104
...rest,
129-
onChange: handleChange,
130-
...(isOnBlur ? { onBlur: handleBlur } : {}),
105+
...(onChangeEvent
106+
? { [onChangeName || 'onChange']: eventWrapper(onChangeEvent) }
107+
: { onChange: handleChange }),
108+
...(isOnBlur
109+
? onBlurEvent
110+
? { [onBlurName || 'onBlur']: eventWrapper(onBlurEvent) }
111+
: { onBlur: handleBlur }
112+
: {}),
131113
value: value || inputValue,
132114
...(isCheckbox ? { checked: inputValue } : {}),
133115
});

src/types.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import * as React from 'react';
2+
3+
export type ValidateResult = string | boolean | undefined;
4+
5+
export type Validate = (data: any) => ValidateResult;
6+
7+
export type ValidationOptionObject<Value> =
8+
| Value
9+
| { value: Value; message: string };
10+
11+
export type ValidationOptions = Partial<{
12+
required: boolean | string;
13+
min: ValidationOptionObject<number | string>;
14+
max: ValidationOptionObject<number | string>;
15+
maxLength: ValidationOptionObject<number | string>;
16+
minLength: ValidationOptionObject<number | string>;
17+
pattern: ValidationOptionObject<RegExp>;
18+
validate:
19+
| Validate
20+
| Record<string, Validate>
21+
| { value: Validate | Record<string, Validate>; message: string };
22+
}>;
23+
24+
export type EventFunction = (
25+
args: any,
26+
) => {
27+
value?: any;
28+
checked?: boolean;
29+
};
30+
31+
export type Props = {
32+
setValue: (name: string, value: any, trigger?: boolean) => void;
33+
register: (ref: any, rules: ValidationOptions) => (name: string) => void;
34+
unregister?: (name: string) => void;
35+
name: string;
36+
as: React.ReactElement<any>;
37+
type?: string;
38+
rules?: ValidationOptions;
39+
value?: string | boolean;
40+
onChange?: (value: any) => void;
41+
onBlur?: (value: any) => void;
42+
mode?: 'onBlur' | 'onChange' | 'onSubmit';
43+
defaultValue?: string;
44+
defaultChecked?: boolean;
45+
onChangeName?: string;
46+
onChangeEvent?: EventFunction;
47+
onBlurName?: string;
48+
onBlurEvent?: EventFunction;
49+
};

0 commit comments

Comments
 (0)