Unform
Usage with TypeScript
Usage with TypeScript
Unform exposes all type definitions from within it's packages, so it's not necessary to install @types dependencies.
Form with TypeScript
When creating a form component using Unform and TypeScript, there are two main points to remember:
- The
onSubmitfunction can be typed usingSubmitHandler<FormData>whereFormDatais the format of data inputted by user; - If you're using
useRefto access form reference, remember to addFormHandlesas type parameter to it;
1import React, { useRef } from 'react';2import { SubmitHandler, FormHandles } from '@unform/core';3import { Form } from '@unform/web';4import Input from './components/Input';56interface FormData {7 name: string;8 email: string;9}1011const MyForm: React.FC = () => {12 const formRef = useRef<FormHandles>(null);1314 const handleSubmit: SubmitHandler<FormData> = data => {15 console.log(formRef);16 };1718 return (19 <Form ref={formRef} onSubmit={handleSubmit}>20 <Input name="name" />21 <Input name="email" />22 </Form>23 );24};2526export default MyForm;Simple input (ReactJS)
When creating a simple HTML input or any other HTML element used for input source, remember to always extend the element props. In web you can always use the JSX.IntrinsicElements['element'] to get the props adapted to JSX.
Also, in web (ReactJS) remember to reference the global element inside useRef hook and always set the default value to null.
1import React, { useEffect, useRef } from 'react';2import { useField } from '@unform/core';34interface Props {5 name: string;6 label?: string;7}89type InputProps = JSX.IntrinsicElements['input'] & Props;1011const Input: React.FC<InputProps> = ({ name, label, ...rest }) => {12 const inputRef = useRef<HTMLInputElement>(null);1314 const { fieldName, defaultValue, registerField, error } = useField(name);1516 useEffect(() => {17 registerField({18 name: fieldName,19 path: 'value',20 ref: inputRef.current,21 });22 }, [fieldName, registerField]);2324 return (25 <>26 {label && <label htmlFor={fieldName}>{label}</label>}2728 <input29 id={fieldName}30 ref={inputRef}31 defaultValue={defaultValue}32 {...rest}33 />3435 {error && <span>{error}</span>}36 </>37 );38};3940export default Input;Simple input (React Native)
Let's create an InputProps interface for the component.
In addition, we will create an InputReference interface to use on the useRef hook.
We can also tell registerField what kind of value this Entry will store
1import React, { useRef, useEffect, useCallback } from 'react';2import { TextInput, TextInputProps, Text } from 'react-native';3import { useField } from '@unform/core';45interface InputProps extends TextInputProps {6 name: string;7 label: string;8}910interface InputReference extends TextInput {11 value: string;12}1314const Input: React.FC<InputProps> = ({15 name,16 label,17 onChangeText,18 ...rest19}) => {20 const inputRef = useRef<InputReference>(null);2122 const { fieldName, registerField, defaultValue = '', error } = useField(name);2324 useEffect(() => {25 if (inputRef.current) inputRef.current.value = defaultValue;26 }, [defaultValue]);2728 useEffect(() => {29 registerField<string>({30 name: fieldName,31 ref: inputRef.current,32 getValue() {33 if (inputRef.current) return inputRef.current.value;3435 return '';36 },37 setValue(ref, value) {38 if (inputRef.current) {39 inputRef.current.setNativeProps({ text: value });40 inputRef.current.value = value;41 }42 },43 clearValue() {44 if (inputRef.current) {45 inputRef.current.setNativeProps({ text: '' });46 inputRef.current.value = '';47 }48 },49 });50 }, [fieldName, registerField]);5152 const handleChangeText = useCallback(53 (value: string) => {54 if (inputRef.current) inputRef.current.value = value;5556 if (onChangeText) onChangeText(value);57 },58 [onChangeText],59 );6061 return (62 <>63 {label && <Text>{label}</Text>}6465 <TextInput66 ref={inputRef}67 onChangeText={handleChangeText}68 defaultValue={defaultValue}69 {...rest}70 />71 </>72 );73};7475export default Input;