Last active
March 28, 2021 12:15
-
-
Save gchumillas/58baf61613e5f7deb243eb35c825e40a to your computer and use it in GitHub Desktop.
This file contains hidden or 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
import React from 'react' | |
import _ from 'lodash' | |
export type Validator = (val: any) => string | true | |
const useValidator = ({ | |
defaultValidator = () => true, | |
validators | |
}: { | |
defaultValidator?: Validator | |
validators?: | |
| { [name: string]: Validator[] } | |
| ((defaultValidator: Validator) => { [name: string]: Validator[] }) | |
}) => { | |
const [texts, setTexts] = React.useState<{ [name: string]: string | true }>({}) | |
return { | |
test: (values: { [name: string]: any }, options?: { debug: boolean }) => { | |
const texts = _.mapValues(values, (value, name) => { | |
const v = _.isFunction(validators) ? validators(defaultValidator) : validators | |
const fieldValidators = v?.[name] || [defaultValidator] | |
for (const validator of fieldValidators) { | |
const result = validator(value) | |
if (typeof result == 'string') { | |
options?.debug && console.info(`validator: ${name} is not valid`) | |
return result | |
} | |
} | |
return true | |
}) | |
setTexts(texts) | |
return _.every(texts, x => _.isEmpty(x)) | |
}, | |
text: (name: string) => { | |
const text = texts[name] | |
return typeof text == 'string' ? text : undefined | |
} | |
} | |
} | |
export default useValidator |
This file contains hidden or 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
import React from 'react' | |
import { Button, TextField } from '@material-ui/core' | |
import useValidator from 'src/lib/validator' | |
const CustomTextField = ({ errorText, ...rest }) => { | |
return <TextField error={!!errorText} helperText={errorText} {...rest} /> | |
} | |
const TestPage = () => { | |
const [message, setMessage] = React.useState('') | |
const [item, setItem] = React.useState({ | |
username: '', | |
password: '', | |
rePassword: '', | |
gender: '' | |
}) | |
const validator = useValidator({ | |
// Default validator (applied when no validator is specified) | |
defaultValidator: val => !!val || 'Required field', | |
// Custom validators | |
validators: defaultValidator => ({ | |
// rePassword is required (defaultValidator) and should be equal to password | |
rePassword: [defaultValidator, val => val == item.password || 'Passwords do not match'], | |
// Gender is not required, but when specified it must be one of the following values: | |
gender: [val => !val || ['male', 'female', 'butterfly'].includes(val) || 'Unknown gender'] | |
}) | |
}) | |
const onFieldChange = name => event => { | |
setItem(item => ({ ...item, [name]: event.target.value })) | |
} | |
const onSubmit = () => { | |
if (!validator.test(item)) { | |
setMessage('No no no...') | |
return | |
} | |
setMessage('Hooray! you got it!') | |
} | |
return ( | |
<> | |
<CustomTextField | |
required | |
label="Username" | |
value={item.username} | |
onChange={onFieldChange('username')} | |
errorText={validator.text('username')} | |
/> | |
<CustomTextField | |
required | |
type="password" | |
label="Password" | |
value={item.password} | |
onChange={onFieldChange('password')} | |
errorText={validator.text('password')} | |
/> | |
<CustomTextField | |
required | |
type="password" | |
label="Repeat password" | |
value={item.rePassword} | |
onChange={onFieldChange('rePassword')} | |
errorText={validator.text('rePassword')} | |
/> | |
<CustomTextField | |
label="Gender" | |
value={item.gender} | |
onChange={onFieldChange('gender')} | |
errorText={validator.text('gender')} | |
/> | |
<Button onClick={onSubmit}>Submit</Button> | |
<p>{message}</p> | |
</> | |
) | |
} | |
export default TestPage |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment