-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2c173f1
commit bb8db18
Showing
1 changed file
with
90 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,98 @@ | ||
# React + TypeScript + Vite | ||
## JSON-TO-FORM | ||
|
||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. | ||
This project focuses on demonstrating the Dependency Injection(DI) pattern by transforming a JSON schema into an HTML form. | ||
|
||
Currently, two official plugins are available: | ||
Here the JSON schema acts a depenedency to the `SchemaRenderer` component. This component requires JSON schema so that it can map over to this object and rendered the required input fields for the form. | ||
|
||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh | ||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh | ||
### Inspiration | ||
|
||
## Expanding the ESLint configuration | ||
I got inspired to make this project when I was debugging a friends react based form. It had a lot of explicit conditional cases based on the specific input field which made that form more prudent to new changes. | ||
|
||
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: | ||
I found JSON schema driven form based soltions, which I found to be extensible and easily configurable and testable. | ||
|
||
- Configure the top-level `parserOptions` property like this: | ||
### Approach | ||
|
||
```js | ||
export default { | ||
// other rules... | ||
parserOptions: { | ||
ecmaVersion: 'latest', | ||
sourceType: 'module', | ||
project: ['./tsconfig.json', './tsconfig.node.json'], | ||
tsconfigRootDir: __dirname, | ||
}, | ||
} | ||
``` | ||
- Here is the approach that I took to implement the project: | ||
|
||
- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked` | ||
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked` | ||
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list | ||
- Every JSON schema should have the following format/fields so that we can call it a valid schema: | ||
|
||
```ts | ||
type TField = { | ||
type: "field"; | ||
dataType: "number" | "text" | "email"; | ||
fieldName: string; | ||
accessorKey: string; | ||
validation?: | ||
| { | ||
required?: | ||
| { | ||
value: boolean; | ||
message: string; | ||
} | ||
| undefined; | ||
maxLength?: | ||
| { | ||
value: number; | ||
message: string; | ||
} | ||
| undefined; | ||
minLength?: | ||
| { | ||
value: number; | ||
message: string; | ||
} | ||
| undefined; | ||
max?: | ||
| { | ||
value: number; | ||
message: string; | ||
} | ||
| undefined; | ||
min?: | ||
| { | ||
value: number; | ||
message: string; | ||
} | ||
| undefined; | ||
pattern?: | ||
| { | ||
value: string; | ||
message: string; | ||
} | ||
| undefined; | ||
} | ||
| undefined; | ||
}; | ||
|
||
type GroupFieldType = { | ||
type: "group"; | ||
orientation: "horizontal" | "vertical"; | ||
fields: (TField | GroupFieldType)[]; | ||
}; | ||
``` | ||
|
||
- Check the JSON schema input as per the above type by parsing it with [zod's schema parser](https://zod.dev/?id=basic-usage). | ||
- Next, we pass this schema to `SchemaRenderer` component that renders each `field` type object with the `input` element. | ||
- We make use of the react-hook-form to manage the form state and updates. | ||
- Lastly, we unregister fields from the form state when any field is removed from the schema. | ||
|
||
### Advantages | ||
|
||
With the help of the DI pattern we are able to easily configure forms. Making changes into the form is a breeze since we only need to change the JSON schema. | ||
|
||
Here is a simple example of adding and removing fields | ||
|
||
// video | ||
|
||
You can also add validation to the form from the JSON schema itself: | ||
|
||
// video that includes validation | ||
|
||
You can read more about dependency injection pattern in react [here](https://blog.logrocket.com/dependency-injection-react/). | ||
|
||
### Libraries | ||
|
||
- [react-hook-form](https://react-hook-form.com/) | ||
- [shadcn-ui](https://ui.shadcn.com/) | ||
- [codemirror-react](https://uiwjs.github.io/react-codemirror/) | ||
- [zod](https://zod.dev/) |