Skip to content

Commit

Permalink
Move rules onto the individual inputs!
Browse files Browse the repository at this point in the history
  • Loading branch information
zackify committed Mar 9, 2021
1 parent 20d03ee commit 1d27337
Show file tree
Hide file tree
Showing 18 changed files with 7,738 additions and 5,763 deletions.
74 changes: 23 additions & 51 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,39 +12,31 @@ single dependency, simplest way to validate and manage form state with hooks in
## Install

```
npm install react-validify
npm install react-validify lodash
```

## Getting Started

This api has been carefully thought out over the past year. It's been in use on multiple React websites and React Native mobile applications. Using the library is simple. Include the `Form` component, and wrap your `input`'s and `submit` buttons.

```js
import Input from './input';
import Submit from './submit';
import { Form, rules } from 'react-validify';
import Input from "./input";
import Submit from "./submit";
import { Form, rules } from "react-validify";

const { required, email } = rules;

const App = () => {
let [values, setValues] = React.useState({
email: 'test',
nested: { test: 'this is nested' },
email: "test",
nested: { test: "this is nested" },
});

return (
<Form
values={values}
onValues={setValues}
rules={{
email: [required, email],
date1: [greaterThanDate2],
name: [required],
}}
>
<Input name="email" />
<Input name="name" />
<Input name="date1" />
<Form values={values} onValues={setValues}>
<Input name="email" rules={[required, email]} />
<Input name="name" rules={[required]} />
<Input name="date1" rules={[greaterThanDate2]} />
<Input name="date2" />
<Input name="nested.test" />
<Submit />
Expand All @@ -57,11 +49,11 @@ Add `useField` to your own inputs inside the Form wrapper. This allows you to us
It just needs to support a `handleChange` `handleBlur` and `value` prop. This is the `Input` component you see in the first example. Don't forget to pass the field `name` to the hook.

```js
import React from 'react';
import { useField } from 'react-validify';
import React from "react";
import { useField, UseFieldProps } from "react-validify";

const Input = ({ name }) => {
let { handleChange, handleBlur, value, errors } = useField(name);
const Input = ({ name, rules }: UseFieldProps) => {
let { handleChange, handleBlur, value, errors } = useField({ name, rules });

return (
<div>
Expand All @@ -70,7 +62,7 @@ const Input = ({ name }) => {
name={name}
value={value}
onBlur={handleBlur}
onChange={event => handleChange(event.target.value)}
onChange={(event) => handleChange(event.target.value)}
/>
</div>
);
Expand All @@ -80,15 +72,15 @@ const Input = ({ name }) => {
Add `useSubmit` to trigger submitting or validating:

```js
import React from 'react';
import { useSubmit } from 'react-validify';
import React from "react";
import { useSubmit } from "react-validify";

const Submit = props => {
const Submit = (props) => {
let { canSubmit, handleSubmit } = useSubmit();

return (
<div
onClick={() => handleSubmit(values => console.log('submit!', values))}
onClick={() => handleSubmit((values) => console.log("submit!", values))}
style={{ opacity: canSubmit ? 1 : 0.5 }}
>
Submit Form
Expand All @@ -97,6 +89,7 @@ const Submit = props => {
};
export default Submit;
```

The callback passed to `handleSubmit` will only be triggered if validation is passing.

Create rules:
Expand All @@ -113,13 +106,15 @@ Rules are guaranteed to run on a field after the first time the field is blurred
## TypeScript Support

With TS enabled, you can create a type for your form values, like so:

```tsx
type Values = {
email: string;
date1?: string;
name?: string;
};
```

Now when we use the form, it looks like this:

```tsx
Expand All @@ -131,35 +126,13 @@ let [values, setValues] = useState<Values>({
<Form
values={values}
onValues={setValues}
rules={{
email: [required, email],
date1: [greaterThanDate2],
name: [required],
fakeField: [] // this will error now
}}
>
<Input name="email" />
<Input name="email" rules={[required, email]}/>
</Form>
)
}
```

TS will infer the values object from the type, since we gave it to `useState`. This means, our rules object can be validated. If you accidentally leave a key for an old field in the rules object, TS will throw an error for you.

You can explicitly set the type like this if you wanted:

```tsx
<Form<Values>
values={values}
onValues={setValues}
rules={{
email: [required, email],
}}
>
<Input name="email" />
</Form>
```

## Contributors

Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)):
Expand All @@ -169,7 +142,6 @@ Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds
| [<img src="https://avatars0.githubusercontent.com/u/449136?v=4" width="100px;"/><br /><sub>Zach Silveira</sub>](https://zach.codes)<br /> | [<img src="https://avatars1.githubusercontent.com/u/2430381?v=4" width="100px;"/><br /><sub>Ryan Castner</sub>](http://audiolion.github.io)<br /> |
| :---------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------: |


<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
20 changes: 8 additions & 12 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,14 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"@types/jest": "^24.0.0",
"@types/node": "^12.0.0",
"@types/react": "^16.9.0",
"@types/react-dom": "^16.9.0",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-scripts": "3.3.0",
"react-validify": "5.7.0",
"typescript": "~3.7.2"
"@types/node": "^14.14.32",
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.2",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-scripts": "4.0.3",
"react-validify": "6.0.3",
"typescript": "4.2.3"
},
"scripts": {
"start": "react-scripts start",
Expand Down
32 changes: 12 additions & 20 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import React from 'react';
import React from "react";

import Input from './input';
import Submit from './submit';
import { required, email, RuleFn } from 'react-validify/dist/rules';
import { Form } from 'react-validify';
import Input from "./input";
import Submit from "./submit";
import { required, email, RuleFn } from "react-validify/lib/rules";
import { Form } from "react-validify";

const greaterThanDate2: RuleFn = (value, values) => {
if (!values.date2) return false;

if (value.length < values.date2.length)
return 'Must be longer date than date 2';
return "Must be longer date than date 2";
};

type TestValues = {
Expand All @@ -19,21 +19,13 @@ type TestValues = {
};

const App = () => {
let [values, setValues] = React.useState<TestValues>({ email: 'test' });
//console.log(values, 'herere');
let [values, setValues] = React.useState<TestValues>({ email: "test" });

return (
<Form
values={values}
onValues={setValues}
rules={{
email: [required, email],
date1: [greaterThanDate2],
name: [required],
}}
>
<Input name="email" />
<Input name="name" />
<Input name="date1" />
<Form values={values} onValues={setValues}>
<Input name="email" rules={[required, email]} />
<Input name="name" rules={[required]} />
<Input name="date1" rules={[greaterThanDate2]} />
<Input name="date2" />
<Submit />
</Form>
Expand Down
12 changes: 5 additions & 7 deletions example/src/input.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import React from 'react';
import { useField } from 'react-validify';

const Input = props => {
let { handleChange, handleBlur, value, errors } = useField(props.name);
import { useField } from "react-validify";

const Input = (props) => {
let { handleChange, handleBlur, value, errors } = useField(props);
return (
<div>
{errors ? <p>{errors[0]}</p> : null}
<input
{...props}
value={value || ''}
value={value || ""}
onBlur={handleBlur}
placeholder={props.name}
onChange={event => handleChange(event.target.value)}
onChange={(event) => handleChange(event.target.value)}
/>
</div>
);
Expand Down
10 changes: 5 additions & 5 deletions example/src/submit.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React from 'react';
import { useSubmit } from 'react-validify';
import { useSubmit } from "react-validify";

const Submit = props => {
let { canSubmit, values } = useSubmit();
const Submit = (props) => {
let { canSubmit, handleSubmit } = useSubmit();

return (
<div
onClick={() => {
if (canSubmit) return console.log('submit!', values);
if (canSubmit)
return handleSubmit((values) => console.log("submit!", values));
}}
style={{ opacity: canSubmit ? 1 : 0.5 }}
>
Expand Down
3 changes: 2 additions & 1 deletion example/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react"
"jsx": "react-jsx",
"noFallthroughCasesInSwitch": true
},
"include": [
"src"
Expand Down
Loading

0 comments on commit 1d27337

Please sign in to comment.