{"id":15064866,"url":"https://github.com/devyatsu/reusable-react-form","last_synced_at":"2026-02-27T17:43:38.763Z","repository":{"id":183413904,"uuid":"657753487","full_name":"DevYatsu/reusable-react-form","owner":"DevYatsu","description":"An efficient react form component using react-hook-form and tailwind css.","archived":false,"fork":false,"pushed_at":"2023-06-26T01:04:15.000Z","size":43732,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-11T17:47:49.436Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DevYatsu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-06-23T19:13:33.000Z","updated_at":"2023-06-25T23:56:41.000Z","dependencies_parsed_at":null,"dependency_job_id":"ae975be6-973c-4f93-b363-8e5ea222b946","html_url":"https://github.com/DevYatsu/reusable-react-form","commit_stats":null,"previous_names":["devyatsu/reusable-react-form"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevYatsu%2Freusable-react-form","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevYatsu%2Freusable-react-form/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevYatsu%2Freusable-react-form/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevYatsu%2Freusable-react-form/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DevYatsu","download_url":"https://codeload.github.com/DevYatsu/reusable-react-form/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243790999,"owners_count":20348385,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-09-25T00:27:25.747Z","updated_at":"2026-02-27T17:43:38.723Z","avatar_url":"https://github.com/DevYatsu.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ReusableReactFormComponent\nThis repository contains a reusable form component built with React Hook Form and Tailwind CSS. \nThe form component provides an easy and efficient way to handle form validation, user input, and form submission in React applications.\n\n## Features\n- Utilizes React Hook Form for form validation and state management.\n* Integrates Tailwind CSS for styling and responsive design.\n+ Supports various input types, such as text, email, password, etc.\n- Customizable form fields with validation rules.\n* Easy integration with existing React projects.\n+ Lightweight and performant.\n\n## Installation\n\nThere are actually two ways to use our Form Component, either use the data property of the component or insert Input, Select and TextArea components as children of the Form Component. We will first cover the data prop method then the children components method.\nTo use the form component in your project, follow these steps:\n\n## 1. Install **reusable-react-hook** library:\n- `npm install reusable-react-hook` \n- `pnpm install reusable-react-hook`\n- `yarn add reusable-react-hook`\n\n## 2. Import the form component into your React application:\n\n```typescript\nimport { Form } from 'reusable-react-form/lib';\n//import { NextForm as Form } from 'reusable-react-form/lib'; if using nextjs\n\nfunction App() {\n  return (\n    \u003cdiv className=\"App\"\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n## 3. How does the component work ?\n\nKeep in mind that the component needs at least two parameters to work, these parameters are:\n- data: an array of objects defining which components should the form contain\n- submitURL: a string of the url to POST the data on when user submits the form\n\n```typescript\n\nconst data = \n  [\n    {element: \"input\", name:\"test\", placeholder: \"enter sth\"} \n    // each object represents either an input, a select or a textarea\n  ];\n\n```\n\n## 4. Add the minimal parameters for the Form to works correctly\n\nThe name property in objects contained in the data array must be written in CamelCase.\n\n```typescript\nimport { Form } from 'reusable-react-form/lib';\n\nconst data = [\n{\n  name: \"inputName\", // in CamelCase\n  placeholder: \"Enter something...\",\n}\n];\n//data is an array of all the input (represented by objects), textarea and select components\n\nfunction App() {\n  return (\n    \u003cdiv className=\"App\"\u003e\n      \u003cForm \n          data={data} \n            //represents the informations on the different elements in the form\n   \n          submitURL=\"/api/urlToPostOn\" \n             // the url the data entered in the form will be posted to\n      /\u003e\n    \u003c/div\u003e\n  );\n}\n```\nThese are the minimum requirements for the Form to work correctly.\nThe form will be composed of one input with the name and placeholder put in the data array.\n\nYou can check all the possbile arguments attributable to the form component in the types/form.ts file even tough we will see most of them in the next sections.\n\n## 5. Customize the form fields and validation rules according to your requirements.\n\nWe can take a look at the possibilities regarding the customization of the form fields:\n\n```typescript\nimport { Form } from 'reusable-react-form/lib';\n\nconst data = [\n{\n  // the form will check if the input possessess a label key\n  // if it does it will be used as label, elsewhere the name\n  // will be used, set it in camelCase in case\n  name: \"familyName\", \n  label: \"family name\",\n  placeholder: \"Enter something...\",\n  type: \"password\", //all possible input types, default is obviously set to \"text\" \n  minLength: 6, //set a min length\n  maxLength: {\n    value: 34, //set a max length\n    message: \"Password cannot exceed 34 characters long\" \n    //error message displayed when maxLength is not respected, you can do the same with minLength\n  },\n  required: true\n},\n{\n  name: \"inputName2\", // name must be unique\n  placeholder: \"Enter something...\",\n  type: \"number\",\n  min: {\n    value: 0,\n    message: \"Number must be positive\"\n  },\n  required: \"number is required\" \n   //same as required: true, here is a way to directly set the error message\n}, \n{\n  element: \"select\",\n  name: \"pickAFlavour\", // name of the select (unique as well)\n  values: [ // the options of the select\n    {value: \"1\", displayValue: \"chocolate\"}, \n     //option with type {value: string; displayValue: string;}\n    {value: \"2\", displayValue: \"vanilla\"}\n  ]\n}, \n{\n  element: \"textarea\",\n  name: \"PostAComment\",\n  placeholder: \"enter a comment...\",\n  required: true,\n}, \n{//when element prop is not explicitly set to \"textarea\" or \"select\", element is an input\n  name: \"passwordConfirm\",\n  type: \"password\", \n  isPasswordConfirm: true \n//boolean useful in this case only to ensure the password and passwordConfirm inputs have the same value\n//it will compare this input with the input NAMED \"password\" and only this one\n} \n];\n\nfunction App() {\n  return (\n    \u003cdiv className=\"App\"\u003e\n      \u003cForm \n          data={data} \n          submitURL=\"/api/urlToPostOn\" \n      /\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\nIn this code are covered most of the possibilities regarding the customization of the elements composing the form.\nWe can now look at the customization of the parameters on the Form component.\n\n## 6. Form Component Customization\n\n```typescript\nimport { Form, genInput, genSelect, genTextArea } from 'reusable-react-form/lib';\n\nconst data = [//name       //placeholder\nformInput(\"testInput\", \"Enter some text...\", {//options in an object\n   minLength: {\n      value: 1,\n      message: \"min length is 1\"\n   }//you can also add form inputs like this\n}),\nformSelect(\"testSelect\", \n[{value: \"test\", displayedValue:\"hehe test\"}, {value: \"test2\", displayedValue:\"hehe test2\"}]\n),\nformTextArea(\"testTextArea\", \"placeholder...\", {rows: 5})\n];             //name                          //options, row defaults to 6\n\nfunction App() {\n  return (\n    \u003cdiv className=\"App\"\u003e\n      \u003cForm \n          data={data} // (FormInputProps | FormSelectProps | FormTextAreaProps)[] \n          // you can check all the props in the types/form.ts file, \n          // though most of them are in the example above\n  \n          submitURL=\"/api/urlToPostOn\" // (string) \n  \n          goal=\"register\" // (\"register\" | \"login\" | undefined)\n          //may be either \"register\"|\"login\", allows some automatic customization of the form\n          // still I recommand to use one of them if the form is for one of these purposes\n  \n          title=\"My Form\" // (string | undefined)\n          // set a customized title, the goal param also sets a title when used\n  \n          className=\"pt-5 mb-2 bg-red-500 text-orange-600 etc.\" // (string | undefined) \n  \n          isSimpleForm={true} // (boolean | undefined)\n          // default set to false, not recommended except when using textarea alone\n\n          mistakeInstruction={\"Not Registered yet? Join Now\"}\n          //(string | [href: string; instruction: string] | undefined)\n          // instruction set at the end of the form\n          // when using the goal parameter, it is automatically set\n          // otherwise it's value is \"\" except if you set it yourself\n          //you can also set an url it will redirect to with an anchor onClick\n          //this URL defaults to \"/\" \n  \n          extraData={{postUser: \"DevYatsu\"}} // (Record\u003cstring, any\u003e | undefined)\n          // data that will be add to form data when POST request is made\n\n          successRedirectionURL={\"/\"} // (string | undefined)\n          //URL on which user has to be redirected on when data is sent and responded with a status 200\n          //working on the nextJS version of the component with useRouter()\n          //working on the main version with a redirecting function given as parameter (redirectFunction)\n\n          removeRequestProps={[\"passwordConfirm\"]}// (string[] | undefined)\n          //an array of the element names that must be removed before posting the data\n          //for example here passwordConfirm is removed, this way there is only the password that is sent \n          // and no passwordConfirm which may be useless\n\n         redirectFunction={redirect} // ((string) =\u003e void)\n         //a function called to redirect the user on another page\n         //should take one parameter which is the url to redirect on\n         //this parameter is to be set in the successRedirectionURL form parameter\n\n         //only on the component not destined to be used on nextJS\n         //can still be used on nextJS though but I do not recommand it\n      /\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n## 7. Concrete example\n\nLet's suppose we are building a register page on my website.\n\n```typescript\nimport { Form } from 'reusable-react-form/lib';\n\nconst data = [\n{\n    name: \"username\",\n    placeholder: \"John\",\n    minLength: {\n      value: 4,\n      message: \"Username must be at least 3 characters long\",\n    },\n    maxLength: {\n      value: 18,\n      message: \"Username cannot exceed 18 characters long\",\n    },\n    pattern: {\n      value: \"^[a-zA-Z0-9]+(?: [a-zA-Z0-9]+)*$\",\n      message: \"Invalid username.\",\n    },\n    required: \"Username is required\",\n  },\n{name: \"email\", placeholder: \"Your email...\",\npattern: ... \n{\n   name: \"password\", placeholder: \"Your password...\", type: \"password\", \n   minLength:...,\n   maxLength: ...,\n   pattern: ...\n},\n{name: \"passwordConfirm\", placeholder: \"Your password again...\", type: \"password\",\n   minLength: ...,\n   maxLength: ...,\n   pattern: ...\n   isPasswordConfirm: true\n},\n];\n\nfunction App() {\n  return (\n    \u003cdiv className=\"App\"\u003e\n      \u003cNavbar /\u003e\n      \u003cmain\u003e\n         \u003cForm \n          data={data}\n          submitURL=\"/api/register\"\n          goal=\"register\"    \n   \n          successRedirectionURL={\"/login\"} \n         // do not forget to set it up if not using nextjs\n   \n          removeRequestProps={[\"passwordConfirm\"]}\n         /\u003e\n      \u003cmain/\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\nIt's done! As simple as that our component works perfectly!\nBut it is kind of painful to write the data object right ?\nThat's why I wrote in advance a few elements for you!\n\n## 8. Making our forms even simpler!\n\nLet's suppose we are building the same register page as before.\nInstead of rewriting the components from earlier everytime we can simply use the components found with the form!\nWe can find basic but common components in this directory `./utils/formFunctions.ts`\n\n```typescript\nimport { Form, getGenericFormInputsData, genInput } from 'reusable-react-form/lib';\n\nconst data = getGenericFormInputsData(\"username\", \"email\", \"password\", \"passwordCheck\"); \n// in the right order we put the components names as parameters of this function.\n// now the data variable contains the same array with object as before;\n//actually these saved components are more secure and have more restrictions and validation rules\n\nOR YOU CAN EVEN DO THAT\nconst data = \n   [\n      ...getGenericFormInputsData(\"username\", \"email\", \"password\", \"passwordCheck\"), \n      formInput(\"test\", \"enter sth\")\n   ];\n\nfunction App() {\n  return (\n    \u003cdiv className=\"App\"\u003e\n      \u003cNavbar /\u003e\n      \u003cmain\u003e\n         \u003cForm \n          data={data}\n          submitURL=\"/api/register\"\n          goal=\"register\"    \n          successRedirectionURL={\"/login\"} // do not forget to set it up if not using nextjs\n          removeRequestProps={[\"passwordConfirm\"]}\n         /\u003e\n      \u003cmain/\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\nIsn't it actually easy ?\nWe've come full circle! \nYou have seen everything there is to seen in my simple project, have fun!\n\n## 9. I haven't told you everything!\nIf you prepare using a more react-friendly approach, I have at last implemented an other way to use the Form component!\n\n### The form component can be used in 2 distinct ways:\n1. Using the data property of the form\n\nAll the examples up there cover this method, so i will be rather quick on this one. You just set an array of objects as value of the data parameter on the form, each object representing one form field, either an input, a select or a textarea. This method cannot be mixed with the other method.\n\n2. Using the Input, Select and TextArea components\n\nYou can import 3 components that can be passed as children of the Form component and that represent the different fields of the form. The two methods are working in a similar way, we are just taking a different approach. The components can take as parameters the same parameters as if they were objects in the data array. Let's see an example real quick!\n\n```typescript\nimport { Form, Input, Select, TextArea } from \"reusable-react-form/lib\";\n\nexport default function App() { \n  return \u003c\u003e\n        \u003cForm submitURL=\"/\"\u003e\n          {/*I would rather consider using the 1st method with the getGenericFormInputsData(\"email\") because the validation regex is more complex and efficient*/}\n            \u003cInput name=\"email\" placeholder=\"Enter your email...\" type=\"email\" pattern={{value: \"^[\\\\w-\\\\.]+@([\\\\w-]+\\\\.)+[\\\\w-]{2,4}$\", message:\"must be a valid email\"}} /\u003e \n            \u003cInput name=\"username\" placeholder=\"The way you want us to call you...\" minLength={4}/\u003e\n            \u003cTextArea name=\"survey\" placeholder=\"How did you hear about us...\" minLength={{value: 20, message: \"please tell us a bit more about it\"}}/\u003e\n            \u003cSelect name=\"gender\" values=[{value: \"male\", displayValue: \"male\"}, {...}] /\u003e\n            \u003cInput name=\"password\" placeholder=\"Enter your password...\" type=\"password\" minLength={{value:8, message: \"password must contain at least 8 characters\"}}/\u003e\n        \u003c/Form\u003e\n    \u003c/\u003e\n} \n\n```\n\nThe 2 methods cannot be mixed together. It means that you either decide to use the data array or the form children components. If you try to mix the two methods, it will produce an error. Use whichever you think is better for what you wish to achieve, may it be a complex form or just a simple form needing at most a username, email and password inputs.\n\n\n## 10. Start using the lib:\nJust a fresh reminder: \n- To install the package\n  \n``npm install reusable-react-form``\n\n- To import the Form in a nextJS project\n```typescript\nimport { NextForm as Form } from \"reusable-react-form/lib\";\n```\n- To import the Form in any other reactJS project\n```typescript\nimport { Form } from \"reusable-react-form/lib\";\n```\n- To import form components\n```typescript\nimport { Input, Select, TextArea } from \"reusable-react-form/lib\";\n```\n- To import third-party functions and utils\n```typescript\nimport { getGenericFormInputsData, genInput, genSelect, genTextArea } from \"reusable-react-form/lib\";\n```\n\nStart using this simple form component and have fun!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevyatsu%2Freusable-react-form","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevyatsu%2Freusable-react-form","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevyatsu%2Freusable-react-form/lists"}