How to get focus from one textinput to another textinput? - reactjs

I have created a custom text input, suppose it to be
Now I want to make user to get focused from one textinput to another. Make it as from
let {login,pass}=useRef(null)
<MyTextInput placeholder'login' ref={login} onSubmitEditing={()=>pass.focus()}/>
<MyTextInput placeholder='password' ref={pass}/>
Now i am working with functional components in react native And I have tried adding ref to both of it as above. But I am getting error as cannot cannot read property focus of undefined.
Can anyone help me adding focus with this kind of textinputs?

Here is a simple snippet that should work in your case assuming your custom MyTextInput supports the same props as TextInput
export default function App() {
const useranme = React.useRef(null)
const password = React.useRef(null)
return (
<View>
<MyTextInput onSubmitEditing={()=>password.current.focus()} ref={useranme} />
<MyTextInput ref={password} />
</View>
);
}

Related

React - issue with initialValues ant design when using referenced component

Using ant design input and forms, I am having trouble using intialValues when a component is referenced in. In this case, I am trying to pass in CustomInput.js, a ant design Input, into my form as <Component/>. Everything works except the initialValues.
Any ideas what to do to make intialValues work?
https://codesandbox.io/s/initialvalues-forked-keftp?file=/index.js:382-414
You have to pass the props from your custom component down to Input, specifically the value prop:
function CustomInput(
{ field, value = "", onChange = (e) => {}, disabled, ...rest },
ref
) {
return (
<Input
ref={ref}
value={value}
onChange={onChange}
disabled={disabled}
{...rest}
/>
);
}
DEMO
Note: I'm unsure as to what your field prop is. Since it's not a supported prop as part of the component's API, I left it out.

React native multiple ref to global component

I want to create multiple ref's to the same global component. Like for example TextInput , if i want to add ref to it i use. this in my class based component :
<TextInput
ref={input => {
this.secondTextInput = input;
}}
/>
and then call via this.secondTextInput.focus(); to focus the textinput. It works as long im importing the whole textInput directly in my class.
Similiarly if ive created a global component for TextInput in another file like :
export const OTPInput = props => {
return (
<TextInput
placeholder={props.title}
onChangeText={props.onTextEnter}
value={props.value}
/>
);
};
and using this in my classes by importing like :
Class ABC extends Component{
render(){
return(
<>
<OTPInput title ="first otp" />
<OTPInput title ="another otp" />
</>
)
}
}
How can i create ref and pass it , so that i can focus the text input by clicking some button in my class func .
Any help would be greatful
Forwarding Refs
export const OTPInput = React.forwardRef((props, ref) => (
<TextInput
ref={ref}
placeholder={props.title}
onChangeText={props.onTextEnter}
value={props.value}
/>
));
Then as per your example usage, just create a ref and attach
const OTPInputRef1 = React.createRef();
...
<OTPInput ref={OTPInputRef1} title ="first otp" />
You should take a look at Forwarding refs described here in the react documents
https://reactjs.org/docs/forwarding-refs.html

React Hooks - Input loses focus when 1 character is typed in

I'm playing with React Hooks - rewriting a form to use hook concepts. Everything works as expected except that once I type any 1 character into the input, the input loses focus.
I guess there is a problem that the outside of the component doesn't know about the internal changes in the component, but how do I resolve this issue?
Here is the useForm Hook:
import React, { useState } from "react";
export default function useForm(defaultState, label) {
const [state, setState] = useState(defaultState);
const FormComponent = () => (
<form>
<label htmlFor={label}>
{label}
<input
type="text"
id={label}
value={state}
placeholder={label}
onChange={e => setState(e.target.value)}
/>
</label>
</form>
);
return [state, FormComponent, setState];
}
Here is the component that uses the Hook:
function App() {
const [formValue, Form, setFormValue] = useForm("San Francisco, CA", "Location");
return (
<Fragment>
<h1>{formValue}</h1>
<Form />
</Fragment>
);
}
While answer by Kais will solve the symptoms, it will leave the cause unaddressed. It will also fail if there are multiple inputs - which one should autofocus itself on rerender then?
The issue happens when you define a component (FormComponent) inside the scope of another function which is called each render of your App component. This gives you a completely new FormComponent each time your App component is rerendered and calls useState. That new component is then, well, without focus.
Personally I would feel agains returning components from a hook. I would instead define a FormComponent component, and only return state from useForm state.
But, a working example closest to your original code could be:
// useForm.js
import React, { useState } from "react";
// Define the FormComponent outside of your useForm hook
const FormComponent = ({ setState, state, label }) => (
<form>
<label htmlFor={label}>
{label}
<input
type="text"
id={label}
value={state}
placeholder={label}
onChange={e => setState(e.target.value)}
/>
</label>
</form>
);
export default function useForm(defaultState, label) {
const [state, setState] = useState(defaultState);
return [
state,
<FormComponent state={state} setState={setState} label={label} />,
setState
];
}
// App.js
import useForm from "./useForm";
export default function App() {
const [formValue, Form] = useForm("San Francisco, CA", "Location");
return (
<>
<h1>{formValue}</h1>
{Form}
</>
);
}
Here's a sandbox
When you enter any text in input box. Parent Component is also re-rendering. So you need to make focus on input manually.
For this, use autoFocus in input tag
<input
type="text"
id={label}
value={state}
placeholder={label}
onChange={e => setState(e.target.value)}
autoFocus
/>
The above answers didn't work for me. The solution that worked for me was much simpler and, for that reason, less obvious.
The Problem
Essentially, the value that I was changing with the input was also being used for each key in a list of inputs.
Hence, when I updated the value the key would change and React would detect that it's different relative to the last key and create a new input in its place. As a new input it wouldn't focus on itself.
However, by using autoFocus it would automatically focus on the newly created input. But the issue wasn't fixed as it was obvious that the input was continually going through a cycle of un-focus and focus.
Here's an article demonstrating the problem.
The Fix
Update the key to an unchangeable value so React would have a stable reference to the list items. In my case I just updated it to the index. This is not ideal (React docs recommend using a stable ID), but in my situation it was okay because the order of the items won't change.
The first solution actually worked for me , initially the functional component which contained the text field was part of the main functional component , i was facing the same issue but when i extracted the text-field component into another page and imported it it worked fine
This was my component
<Paper >
<div>
<div style={{padding:'10px' ,display:'flex'}} >
<inputstyle={{marginRight:'5px'}} value={val} onChange={(e)=>{setVal(e.target.value)}} />
</div>
</div>
</Paper>

How to set or clear value of material-ui Input in ReactJS

I am unable to clear the value of a material-ui Input using refs, not state.
I've tried both types of refs that I know about:
ref={this.input}
- and -
ref={el => (this.input = el)}
but neither seems to work w/ a material-ui Input
the following similar questions did not help:
How to get input value of TextField from Material UI?
Clear and reset form input fields
Clear an input field with Reactjs?
how to set Input value in formField ReactJs
Here's a snippet of my React JSX for the input & button:
<Input
type="text"
id="name"
inputComponent="input"
ref={el => (this.name = el)}
/>
<Button
variant="contained"
onClick={this.handleClear}
className="materialBtn"
>
Clear
</Button>
And the event handler that I expect should clear the input value:
handleClear() {
this.name.value = "";
}
I can make the code work fine using a standard HTML5 input, but not with a material-ui input, which is a requirement of this project. Additionally, this element's value is NOT in react state and I am not looking for a solution that requires using state -- I need to keep this piece as an uncontrolled component.
What am I missing w/ regard to material-ui? I have combed their docs/api but haven't found anything that suggests it needs to be handled differently from a standard input. thanks
Here's an example on CodeSandbox showing the failure w/ a material-ui input and success w/ an HTML5 input:
https://codesandbox.io/s/fancy-frost-joe03
I figured it out, you are using the wrong prop for the ref.
You should be using inputRef prop.
Here is the correct version,
<Input
type="text"
id="name"
inputComponent="input"
inputRef={el => this.name = el}
/>
<Button
variant="contained"
onClick={this.handleClear}
className="materialBtn"
>
Clear
</Button>
handleClear() {
this.name.value = "";
}
The reason is that the Material Input component creates an element with the following structure,
<div class="MuiInputBase-root MuiInput-root MuiInput-underline">
<input class="MuiInputBase-input MuiInput-input" id="name" type="text" value=""></input>
</div>
So, using ref would reference the root element which is <div>. So, they created a separate prop called inputRef to reference the child element <input>.
I updated your codesandbox.io code and saved it. Check out the full working code here,
https://codesandbox.io/s/elastic-dhawan-l4dtf
import React, { useState } from 'react'
import { Button, Container, InputBase } from '#material-ui/core'
const ClearText = ()=> {
const [text , setText] = useState("")
}
const clearTextField = () => setText("")
return (
<Container>
<InputBase
value={text ? text : ""}
onChange={(e)=>setText(e.target.value)}
/>
<Button onClick={clearTextField} > Clear </Button>
</Container>
)
};
export default ClearText;

Selecting an element in React in a stateless function component in React?

<TextField
onChange={props.onChangeTextField}
ref="questionInput"
style={styles.textField}
value={props.existingValue}
fullWidth={true}
/>
I was trying to give an input field in a stateless function component to be able to focus it when the component loads like this:
componentWillMount = () => {
this.refs.questionInput.focus();
console.log('test')
}
}
But I got the error:
Stateless function components cannot have refs.
So is there a way to focus an input field in React without a ref?
You should wrap your input component with forwardRef function. Something like this:
import * as React from "react";
const TextInput = React.forwardRef(
(props, ref) => <input ref={ref} {...props} />
);
export default TextInput;
Note that it will add a second argument to your functional component, which you should pass to the DOM element as ref prop.
Yes. However your method of using ref is really outdated. You should update to the latest version of React (currently 16.3.2) and follow the official documentation
function CustomTextInput(props) {
// textInput must be declared here so the ref can refer to it
let textInput = React.createRef();
function handleClick() {
textInput.current.focus();
}
return (
<div>
<input
type="text"
ref={textInput} />
<input
type="button"
value="Focus the text input"
onClick={handleClick}
/>
</div>
);
}
No, you need to change the functional component into a class.
You may not use the ref attribute on functional components because they don’t have instances
You should also use the newer callback API to set the ref:
ref={ref => { this.questionInput = ref }}
Or createRef for v16.3.
Adding the autoFocus prop to the input component might do the trick if you just want it to be focused on mount:
<TextField autoFocus ..restOfProps />

Resources