Open sachin8094 opened 5 years ago
@sachin8094 sorry to hear it isn't working for you within a functional component with hooks. I have never used either of those before. If anyone out there has any suggestions on how this works or if it works please chime in.
To me it all seems right. But you aren't doing this.forceUpdate()
which may be done in a different way when using hooks, but Im guessing you may need to force rerender once you show the messages for the first time?
@sachin8094 The problem is that you are creating a new validator instance on every render. You need to use some other pattern to make sure it's a singleton. The simplest workaround I came up with right off the bat is to store the validator in a state hook (don't need a setState since you don't want to change it).
const [validator] = React.useState(new SimpleReactValidator({...}))
It might make sense to useMemo or useEffect. I wasn't sure about useMemo though since the docs say "You may rely on useMemo as a performance optimization, not as a semantic guarantee." Maybe a useEffect would work? I haven't tried but maybe:
let validator; React.useEffect(() => { validator = new SimpleReactValidator({...}); }, []);
I don't know if this would work or when the effect would run, I can test that out later. But I know the first pattern with useState works.
You can use useRef for this kind of job. https://stackoverflow.com/a/53146714/5160696
@sachin8094 Did you try to validate your input in the onBlur event? It works for me.
const [address, setAddress] = useState()
const simpleValidator = useRef(new SimpleReactValidator())
<Input
name="name"
value={companyInformation.name}
onChange={handleInputChange}
onBlur={simpleValidator.current.showMessageFor('name')} />
{simpleValidator.current.message('name', companyInformation.name, 'required')}
You can also use force update after a form submit to show all the messages at once:
const simpleValidator = useRef(new SimpleReactValidator())
const [, forceUpdate] = useState();
submitForm() => {
const formValid = simpleValidator.current.allValid()
if (!formValid) {
simpleValidator.current.showMessages()
forceUpdate(1)
}
}
If you can use forceUpdate with hooks like that then you can initialize the SRV with forceUpdate so it will do it automatically. something like this:
const [, forceUpdate] = useState()
const simpleValidator = useRef(new SimpleReactValidator({autoForceUpdate: {forceUpdate: forceUpdate}))
submitForm() => {
const formValid = simpleValidator.current.allValid()
if (!formValid) {
simpleValidator.current.showMessages()
}
}
I have created one small hooks to solve this problem. It worked for me. Here is the repository: https://github.com/chaudharykiran/SimpleReactValidatorWithHooks
I'm open to adding better support for hooks in SRV. If someone wants to open a PR or talk about some ideas I am open to it.
I want to work on that. cc. @stuyam
@chaudharykiran great! I don't use hooks so someone else would be better suited for the main ideas of what this needs. What is SRV missing that would make it work easier with hooks?
I have created one small hooks to solve this problem. It worked for me. Here is the repository: https://github.com/chaudharykiran/SimpleReactValidatorWithHooks
@chaudharykiran please how do I use showMessageFor on this?
If you can use forceUpdate with hooks like that then you can initialize the SRV with forceUpdate so it will do it automatically. something like this:
const [, forceUpdate] = useState() const simpleValidator = useRef(new SimpleReactValidator({autoForceUpdate: {forceUpdate: forceUpdate})) submitForm() => { const formValid = simpleValidator.current.allValid() if (!formValid) { simpleValidator.current.showMessages() } }
Does not show error messages after submitting form. Shows only when the form is submitted and then the input is changed.
Update: Working. Didn't call forceUpdate.
In my case a hook's solution is working nice. Thanks @chaudharykiran
Awesome good job @h4r3en
please how do I use showMessage on this?
You have to pass true
when you want to show error message.
if (notValid) {
showMessage(true)
}
cc. @dinorhythms
If you can use forceUpdate with hooks like that then you can initialize the SRV with forceUpdate so it will do it automatically. something like this:
const [, forceUpdate] = useState() const simpleValidator = useRef(new SimpleReactValidator({autoForceUpdate: {forceUpdate: forceUpdate})) submitForm() => { const formValid = simpleValidator.current.allValid() if (!formValid) { simpleValidator.current.showMessages() } }
Does not show error messages after submitting form. Shows only when the form is submitted and then the input is changed.
Update: Working. Didn't call forceUpdate.
It does work if you wrap like this:
const useValidator = (customMessage = {}, customValidator = {}): [SimpleReactValidator, Function] => {
const [, forceUpdate] = useState();
const validator = useRef(new SimpleReactValidator({
messages: customMessage,
validators: customValidator,
autoForceUpdate: { forceUpdate: () => forceUpdate(1) }
}));
return [validator.current, forceUpdate];
}
1
save my day!
I found my own solution without using autoForceUpdate by using focus, hope this will help:
State:
// SET FOCUS
const [focusPhoneNumber, setFocusPhoneNumber] = useState(false);
Input:
<input
name="phoneNumber"
value={phoneNumber}
onChange={(e) => handlePhoneNumberChange(e)}
onFocus={(e) => setFocusPhoneNumber(true)}
onBlur={focusPhoneNumber ? simpleValidator.current.showMessageFor('phoneNumber') : () => {}}
placeholder="2984928xxx" type="number" />
{ simpleValidator.current.message('phoneNumber', phoneNumber, 'required|min:9|max:14|numeric') }
and on submit button:
let isValid = validator.current.allValid();
if(!isValid) {
setFocusPhoneNumber(true);
validator.current.showMessages(true);
}
Here is a more advance custom hook to force rerender the component. This hook will not recreate a SimpleReactValidator instance in each rerender, tiny performance boost~
//useSimpleReactValidator.js
export default function useSimpleReactValidator(passInOptions = {}) {
const [{ options }, forceUpdate] = React.useReducer(({ options }) => ({ options }), {
options: passInOptions,
});
const simpleValidator = React.useMemo(
() =>
new SimpleReactValidator(
options.autoForceUpdate
? {
...options,
autoForceUpdate: {
forceUpdate,
},
}
: options
),
[options]
);
return [simpleValidator, forceUpdate];
}
//example
const [validator, forceUpdate] = useSimpleReactValidator({...anyOtherOptions, autoForceUpdate: true});
I have created one small hooks to solve this problem. It worked for me. Here is the repository: https://github.com/chaudharykiran/SimpleReactValidatorWithHooks
This is perfect! Worked like a charm. Appreciate you for adding this.
@sachin8094 Did you try to validate your input in the onBlur event? It works for me.
const [address, setAddress] = useState() const simpleValidator = useRef(new SimpleReactValidator()) <Input name="name" value={companyInformation.name} onChange={handleInputChange} onBlur={simpleValidator.current.showMessageFor('name')} /> {simpleValidator.current.message('name', companyInformation.name, 'required')}
I try this but it's showing errors on page load not on onblur
@sachin8094 Did you try to validate your input in the onBlur event? It works for me.
const [address, setAddress] = useState() const simpleValidator = useRef(new SimpleReactValidator()) <Input name="name" value={companyInformation.name} onChange={handleInputChange} onBlur={simpleValidator.current.showMessageFor('name')} /> {simpleValidator.current.message('name', companyInformation.name, 'required')}
I try this but it's showing errors on page load not on onblur
you need to wrap onBlur={simpleValidator.current.showMessageFor('name')} /> with a function.
onBlur={()=>simpleValidator.current.showMessageFor('name')} />
@sachin8094 Did you try to validate your input in the onBlur event? It works for me.
const [address, setAddress] = useState()
const simpleValidator = useRef(new SimpleReactValidator())
<Input
name="name"
value={companyInformation.name}
onChange={handleInputChange}
onBlur={simpleValidator.current.showMessageFor('name')} />
{simpleValidator.current.message('name', companyInformation.name, 'required')}
I try this but it's showing errors on page load not on onblur
you need to wrap onBlur={simpleValidator.current.showMessageFor('name')} /> with a function.
onBlur={()=>simpleValidator.current.showMessageFor('name')} />
thanks it's working but after filling the correct input message was still there
I have created one small hooks to solve this problem. It worked for me. Here is the repository: https://github.com/chaudharykiran/SimpleReactValidatorWithHooks
Awesome! This works for me. 🚀
Good work @shal0mdave
This works!
const [, forceUpdate] = useReducer((x) => x + 1, 0); const validator = useRef( new SimpleReactValidator({ autoForceUpdate: { forceUpdate: forceUpdate }}) );
Usage: onBlur={validator.current.showMessageFor('name')} />
I am trying to use is in the functional component using React Hooks but its now showing up the validation message on UI
My React version is below "react": "^16.8.6", "react-dom": "^16.8.6",
Below is my code, Please check if I am missing anything.