Skip to content

Instantly share code, notes, and snippets.

@yogeshdecodes
Forked from Sqvall/file-upload.tsx
Created June 29, 2021 10:30
Show Gist options
  • Save yogeshdecodes/11037e897429d43c6134db32d330ca22 to your computer and use it in GitHub Desktop.
Save yogeshdecodes/11037e897429d43c6134db32d330ca22 to your computer and use it in GitHub Desktop.
File Upload with Chakra UI and react-hook-form
import { ReactNode, useRef } from 'react'
import { Button, FormControl, FormErrorMessage, FormLabel, Icon, InputGroup } from '@chakra-ui/react'
import { useForm, UseFormRegisterReturn } from 'react-hook-form'
import { FiFile } from 'react-icons/fi'
type FileUploadProps = {
register: UseFormRegisterReturn
accept?: string
multiple?: boolean
children?: ReactNode
}
const FileUpload = (props: FileUploadProps) => {
const { register, accept, multiple, children } = props
const inputRef = useRef<HTMLInputElement | null>(null)
const { ref, ...rest } = register as {ref: (instance: HTMLInputElement | null) => void}
const handleClick = () => inputRef.current?.click()
return (
<InputGroup onClick={handleClick}>
<input
type={'file'}
multiple={multiple || false}
hidden
accept={accept}
{...rest}
ref={(e) => {
ref(e)
inputRef.current = e
}}
/>
<>
{children}
</>
</InputGroup>
)
}
type FormValues = {
file_: FileList
}
const App = () => {
const { register, handleSubmit, formState: { errors } } = useForm<FormValues>()
const onSubmit = handleSubmit((data) => console.log('On Submit: ', data))
const validateFiles = (value: FileList) => {
if (value.length < 1) {
return 'Files is required'
}
for (const file of Array.from(value)) {
const fsMb = file.size / (1024 * 1024)
const MAX_FILE_SIZE = 10
if (fsMb > MAX_FILE_SIZE) {
return 'Max file size 10mb'
}
}
return true
}
return (
<>
<form onSubmit={onSubmit}>
<FormControl isInvalid={!!errors.file_} isRequired>
<FormLabel>{'File input'}</FormLabel>
<FileUpload
accept={'image/*'}
multiple
register={register('file_', { validate: validateFiles })}
>
<Button leftIcon={<Icon as={FiFile} />}>
Upload
</Button>
</FileUpload>
<FormErrorMessage>
{errors.file_ && errors?.file_.message}
</FormErrorMessage>
</FormControl>
<button>Submit</button>
</form>
</>
)
}
export default App
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment