Blur Any Focused Field onSubmit | React Final Form - reactjs

This might be a bug, but I wanted to post here before I open a GitHub issue to see if the community at large has advice, or if someone can just call me out for doing it wrong.
I want to blur any focused field onSubmit. Simple.
According to the docs, the onSubmit function is passed (values, form) as arguments, and the form api includes ways to get all registered fields, and a method for supposedly bluring any field. Here's the code:
const onSubmit = async (values, form) => {
const fieldsNames = form.getRegisteredFields();
fieldsNames.forEach(name => form.blur(name));
await sleep(300);
window.alert(JSON.stringify(values, 0, 2));
};
I forked the basic example directly from FinalForms docs, and added those two lines to see if I could get their example to work, but it did not. To test, just type into the firstname field, and press your enter key. The field stays focused..
CodeSandbox Demo Here
Final Form: FormApi Docs
Thanks for reading!

form.blur() is how you tell Final Form that the field has been blurred (it marks the field's state as being blurred). It's more of a listener. To actually imperatively blur the field, you'll need a reference to the DOM element.
Something like getElementById('myField').blur().

Related

checkbox don't get first check in react

I'm sorry I'm not that good at English and this is my first time to use this website. So My question might look a little bit strange.
I just wanna make a checkbox. When it got check signal, then I want to make it to express true, and when the checking is removed, then it should express false. But when I use console.log, I found that the first checking don't make any change and after checking is worked like toggle. I don't know why. My code is below, and in third picture, I just checked three time.
enter image description here
enter image description here
enter image description here
The setState function is async, so in the following lines of code inside your updateIsAgreeInfo the state isn't updated yet
You have to store the new value in a variable
Moreover, when setting a state based on old state value, you should use a function in setState instead of the raw value:
setIsAgreeInfo((oldValue) => !oldValue);
Change your updateIsAgreeInfo to this:-
const updateIsAgreeInfo = () =>{
setIsAgreeInfo(!isAgreeInfo);
console.log(isAgreeInfo)
signupPayload.isAgreeInfo = !isAgreeInfo;
}
or send event as a params in updateIsAgreeInfo and then access the current checked value of checkbox using event.target.checked. like:-
const updateIsAgreeInfo = () =>{
setIsAgreeInfo(event.target.checked);
console.log(event.target.checked)
signupPayload.isAgreeInfo = event.target.checked;
}

Why formik is losing focus immediatelly I hit the second field?

I have a form with formik that is losing focus at the second field.
It's seems to be a really basic stuff, but I can't find the problem.
Check this sandbox: https://codesandbox.io/s/create-react-app-forked-m145g
Click on the e-mail field, type anything (or nothing), hit tab to jump to the next field and watch the focus going away.
As you can see, the field is beeing validated, so, I don't know (and would find quite unlikely) if my custom handleBlur function had something to do with it:
const customHandleBlur = (e) => {
if (!values.recaptcha) this._reCaptchaRef.current.execute();
handleBlur(e);
};
This function is responsible to execute Google's recaptcha v3.
What am I doing wrong?
Try changing your customHandleBlur to only execute if you have a value for both email and description.
const customHandleBlur = (e) => {
if (!!values.email && !!values.description && !values.recaptcha) this._reCaptchaRef.current.execute();
handleBlur(e);
};
This will keep the description from losing focus when the this._reCaptchaRef.current.execute() function is called.
It looks like there are other issues to... but this will keep your description field from losing the focus, which is what your question was.

Obtaining Selected Value in React-Select

I'm trying to implement this example that obtains the user selected value, but using the async select version.
I want to obtain the value that the user selected, but going through the docs on react-select this isn't clear how to do. If you set state equal to the inputValue, as soon as you click on the 'submit' button the inputValue is cleared. You get back
" "
instead of
user selected value
I'm not sure how to obtain the user selected value using the async select component. I have my API data successfully populating & filtering the suggestions box, but I can't figure out how to get the selected value.
I've tried numerous methods and lastly tried using the refs approach like in the above link, but the stored value shows up as null. Instead of storing the user selected value. Here is the link to my broken codesandbox.
Can anyone help or point me in the right direction?
Edit
Here is a link to a working demo if anyone gets stuck on this in the future.
So, what you got wrong is props of react-select to get value on on-change. Use onChange instead of onInputChange on your AsyncSelect Component. Both props are for different purpose. Here is a doc for all props available for react-select. https://react-select.com/props
Try code below
textChange = inputValue => { // whole object of selected option
this.setState({ inputValue:inputValue.value });
};
render(){
....
<AsyncSelect
defaultOptions
loadOptions={this.promiseOptions}
onChange={this.textChange} /** onChange triggers only when user change the
options but onInputChange triggers on each change which is for different
purpose like for e.g. when user type, fetch similar options **/
name="options"
/>
}

react-autosuggest with debounce and distinctUntilChanged

Intent:
I'm trying to achieve an ideal search field that will not make any API calls untill:
The debounce time of 350ms has been reached
AND until there's a change in the value of the input field.
What I've tried so far:
I've used a Subject to track for changes in the input field. Every time there's a change in the input field and handleSuggestionsFetchRequested is called, I'm pushing a new value down the Subject using searchString$.next(userInput);
And in the useEffect hook, I'm pipeing the searchString$ with debounceTime(350) and distinctUntilChanged(). Something like this:
useEffect(() => {
searchString$
.pipe(
debounceTime(350),
distinctUntilChanged(),
switchMap(searchString =>
ajax(`https://api.github.com/search/users?q=${searchString}`)
),
map((networkResponse: any) => networkResponse.response.items)
)
.subscribe((suggestions: Array<User>) => setSuggestions(suggestions));
}, [searchString$]);
But the API calls are still going everytime there's a change in the userInput.
The Issue:
I think the issue is that every time the value of the input field changes, I'm setting the state as well:
const handleChange = (
event: React.ChangeEvent<{}>,
{ newValue }: Autosuggest.ChangeEvent
) => {
setUserInput(newValue);
};
This is causing the Component to re-render and calling the useEffect, which is eventually making the API call again and again.
I could be wrong.
How to replicate:
I've created a Sample Code Sandbox that replicates the issue.
Thanks a lot in advance.
Thanks to the comments from yurzui on my tweet, I was able to figure out the reason for the issue.
I was creating a new Subject on every reconciliation as the line:
const searchString$: Subject<string> = new Subject<string>();
was right inside my component function.
I moved it out and it was working like a charm.
NOTE: As suggested by yurzui, don't forget to catch errors in the ajax call otherwise the Subject will die.
I've updated the Code Sandbox Sample, just in case somebody needs to refer to it.

Submitting redux-form form like a normal HTML form if validation passes, touching all fields if not

I'm trying to build a form that will submit like any other HTML form if redux-form validation passes. If validation fails, I want it to touch all the fields and prevent submission.
So I need to either: write my own onSubmit function that will touch the fields if validation fails. Which I'm trying:
This implementation:
handleSubmit (event) {
const {touch, fields} = this.props
if (!allValid(fields)) {
event.preventDefault()
touch(...fields)
}
}
Yields this error: TypeError: Cannot read property 'indexOf' of undefined out of the call to touch. I'm having a lot of trouble tracking down where exactly this error is occurring in the implementation of touch, but it's definitely the call to touch that's causing it.
Using the built-in handleSubmit will get the touching behavior right if validation fails, but I can't figure out how to get it to submit the form like a normal HTML form if validation passes as well without doing something hacky like this:
handleSubmit (event) {
const {touch, fields} = this.props
if (!allValid(fields)) {
event.preventDefault()
this.props.handleSubmit(() => {})()
}
}
Which does work, but seems like a bad way to go about it.
I believe touch is expecting an array of strings not an array of objects. So you're probably wanting touch(...Object.keys(fields)).

Resources