React native multiple ref to global component - reactjs

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

Related

How to get focus from one textinput to another textinput?

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>
);
}

How to set event type in custom child component from parent component?

So, I have a custom, configurable input component which is supposed to be used in few different forms. The "configuration" for the input filed is being handled by the parent components (validations, type of input field, etc.).
The problem is the event type. For example, in one of the forms, I need the event type on the input field to be onBlur and in another form - onKeyDown.
The question is: how can I pass the event type from the parent component which renders the custom input filed?
Disclaimer - I am new to React, quite new to programming and have been looking for a solution for a few days now to no avail.
First, define your component, that holds the <input /> (or function)
class MyClass extends Component {
render() {
// you can extract some of the props if you want to manipulate somehow. Everything else will be saved in rest
const { value, name, ...rest } = this.props;
return (
<input value={value} name={name} {...rest} />
)
}
}
Then, to that new component, you can add any props, that are available for <input/> tag, example:
class Test extends Component {
render() {
return (
<Fragment>
<MyClass value={5} name="Name" onBlur={this.onBlur} onFocus={this.onFocus} />
<MyClass value="Hello, world!" id='randomId' onChange={e => console.log(e.target.value)} />
</Fragment>
)
}
onBlur = e => {
console.log('Blur');
}
onFocus = e => {
console.log('Focus');
}
}
Now you have two different inputs - one is listening for onBlur and onFocus, the other one has id and listens for onChange.

How to get the ref of a child component inside parent component in ReactJS

I have a parent component and a child component as following.
Parent component:
constructor(){
this.refs = React.createRef();
}
setRef(ref) {
console.log(ref)
}
handleChange(e) {
console.log(e)
}
render() {
return(
<ChildComponent ref={this.setRef} handleChange={this.handleChange.bind(this)}/>
)
}
Child Component:
render() {
return(
<input type="text" ref={this.props.ref} onChange={this.props.handleChange.bind(this)} > </input>
)
}
What changes should I do to get the ref value inside the handleChange() function in parent component? Thanks in advance.
If I´m reading correctly you want to access the input element from the parent component?
You have to use another name for your prop as ref is a keyword prop which will automatically assign the component the given variable.
<ChildComponent inputRef={this.setRef} handleChange={this.handleChange.bind(this)}/>
class ChildComponent extends Component {
render() {
return(
<input type="text" ref={this.props.inputRef} onChange= {this.props.handleChange.bind(this)} > </input>
);
}
}
Based on how you want to access the ref you can either set this.refs directly to the prop or set it inside your setRef function.
// either `this.refs` and then usable through `this.refs.current`
<ChildComponent inputRef={this.refs} {...} />
// or `this.setRef` and assign it yourself
setRef = (ref) => {this.refs = ref;}
ref(as well as key btw) is very special prop. It is not accessible in child by this.props.ref.
Shortest way is to use different prop to pass ref forward and backward:
class Parent ...
render() {
...
<Child inputRef={this.inputRef} />
class Child
...
render() {
<input ref={this.props.inputRef} ...
It's most flexible since you may access different ref inside you child component(e.g. inputRef + scrollableContainerRef + popupRef)
But in some cases you want to compose new component for existing code base. Say <input>'s replacement. Sure, in this case you would avoid changing all <input ref={...} /> onto <MyInput refProp={...}>.
Here you may use React.forwardRef. It feels the best with functional components like
export Child = React.forwardRef((props, forwardedRef) => {
...
return ...
<input ref={forwardedRef} />
})
But for class-based component you would rather use ref-prop with different name:
class Child
...
render()
return
...
<input ref={this.props.forwardedRefName} />
export ChildWithForwardRef = React.forwardRef((props, ref) => <Child forwardedRefName={ref} {...props} />)
PS since you will consume what forwardRef returns rather initial component(Child) you may want to specify displayName for it. This way you may be able find it later say with enzyme's find() or easy recognize element in browser's React DevTools
ref work only on native dom element, to make ref work on user defined Component, you need this:
https://reactjs.org/docs/forwarding-refs.html

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 />

Inject a property programatically in react native

I would like to know how to inject a property an object of a component.
Below is the App Container component code
<FormItem element={<FormItemText />} />
Below are the 2 component.
FormItem extends Component {
saysomething(){
console.log("Saying something")
}
render(){
return (
{this.props.element}
)
}
}
and
FormItemText extends Component {
render(){
return (
<TextInput onChangeText={(text) => this.props.saysomething(text)}
)
}
}
How do I pass along the FormItem.saysomething as a property to FormItemText component.
Thanks
You have to use direct manipulation to inject a property programatically.
First add a ref attribute to your FormItemText component.
Create a function to call setNativeProps on your TextInput.onChangeText.
Done!
Note that direct manipulation is computationally intensive - React needs to re-render the component hierarchy each time the opacity changes, even though other properties of the view and its children haven't changed. Usually this overhead isn't a concern but when performing continuous animations and responding to gestures, judiciously optimizing your components can improve your animations' fidelity.
For more information and examples, read React Native Documentation here.
We do something similar to what you're asking.
We have a Form component that accepts a number of FormInputs as children:
<Form>
<FormInput />
<FormInput />
</Form>
The Form needs to give some functions and properties to the FormInput. For example, the FormInput may need to scroll the parent Form when it is focused.
We do this using a React context
https://facebook.github.io/react/docs/context.html
In your example, it would end up looking something like this:
<FormItem>
<FormItemText />
</FormItem>
FormItem extends Component {
getChildContext() {
return { saysomething: this.saysomething };
}
saysomething(){
console.log("Saying something")
}
render(){
return (
{this.props.children}
)
}
}
FormItem.childContextTypes = {
saysomething: PropTypes.func,
};
FormItemText extends Component {
render(){
return (
<TextInput onChangeText={(text) => this.context.saysomething(text)}
)
}
}
FormItemText.contextTypes = {
saysomething: PropTypes.func,
};

Resources