How can I set focus to an Input in react native?
I have some inputs in my code:
<Input
value={CompName}
onChangeText={(text) => this.onChangeText(text, 'CompName')}
style={styles.valueText}
/>
<Input
value={Phone}
onChangeText={(text) => this.onChangeText(text, 'Phone')}
style={styles.valueText}
/>
...
And I validate if it is empty. IF empty, I set a Alert message and I would like to focus on the field. How can I do it?
myFunc = () => {
if(CompName === '' || CompName === undefined){
Alert.alert('Company Name is required.');
// set focus here??
return;
}
...
}
Thanks
firstly, in react-native, it is TextInput. and here is two methods exposed via the native element. they are .focus() and .blur() that will focus or blur the TextInput programmatically.
for use it, you have to set a ref for the TextInput.
<TextInput
value={this.state.compName}
onChangeText={(text) => this.onChangeText(text, 'CompName')}
style={styles.valueText}
ref={(input) => { this.compNameInput = input; }}
/>
myFunc = () => {
if(this.state.compName === '' || this.state.comNam === undefined){
Alert.alert('Company Name is required.');
// set focus here??
this.compNameInput.focus();
return;
}
...
}
I suggest use the state for the compName, like this.state.compName
Related
Version react hook form
^7.27.0
What I tried to follow and without successful
react hook form - Discussions 7818
react hook form - Issues 230
About what I have
I have 4 text field components at my screen, the name of each text field is name, documentation, email, password and I would like to know how can I setup some configuration that it will be pressed the NEXT button at keyboard and will focus the following text fields?
An example that I have inside at my component file, again I would like to press the next button and the next component that I will config, will be focus.
<TextField
name="name"
label={I18n.t('registerPersonal.fullNameLabel')}
placeholder={I18n.t('registerPersonal.fullNameInput')}
icon={<TypographyIcon fill={!!errors.name && theme.colors.attention} />}
error={errors.name?.message}
errors={errors}
control={control}
returnKeyType="next"
/>
<TextField
name="documentation"
label={I18n.t('registerPersonal.documentIdentificationLabel')}
placeholder={I18n.t('registerPersonal.documentIdentificationInput')}
icon={
<DocumentIcon
fill={!!errors.documentation && theme.colors.attention}
/>
}
error={errors.documentation?.message}
control={control}
returnKeyType="next"
/>
Some properties that I get at my personal hook
const {
control,
handleSubmit,
formState: { errors, isValid }
} = useForm({ resolver: yupResolver(schema) })
My component TextField
import { TextInputProps, Text } from 'react-native'
import { Control, useController } from 'react-hook-form'
import { Container, Wrapper, TextInput, Label } from './styles'
import theme from '../../global/styles/theme'
type TextFieldProps = {
placeholder?: string
label?: string
icon?: React.ReactNode
error?: string
errors?: {
[x: string]: any
}
name: string
control: Control
} & TextInputProps
export function TextField(props: TextFieldProps) {
const { placeholder, label, icon, error, errors, name, control, ...rest } =
props
const { field } = useController({
control,
defaultValue: '',
name
})
return (
<>
<Container>
{!!label && <Label>{label}</Label>}
<Wrapper hasLabel={!!label} hasError={!!error}>
{!!icon && icon}
<TextInput
value={field.value}
onChangeText={field.onChange}
placeholder={error ? error : placeholder}
placeholderTextColor={
error ? theme.colors.attention : theme.colors.grayColor
}
{...rest}
/>
</Wrapper>
{errors && errors.name && errors.name.type === 'matches' && (
<Text>{errors.name.message}</Text>
)}
</Container>
</>
)
}
your component must include ref prop like
<TextInput
ref={inputRef} // this one
value={field.value}
onChangeText={field.onChange}
placeholder={error ? error : placeholder}
placeholderTextColor={
error ? theme.colors.attention : theme.colors.grayColor
}
{...rest}
/>
then, you need to create ref from parent for each field
const emailRef = useRef(null);
const passwordRef = useRef(null);
after this, you need to add the props that is
onSubmitEditing={() => passwordRef.current.focus()} // to auto focus password field
finally,
<TextField
onSubmitEditing={() => passwordRef.current.focus()} // here
name="name"
label={I18n.t('registerPersonal.fullNameLabel')}
placeholder={I18n.t('registerPersonal.fullNameInput')}
icon={<TypographyIcon fill={!!errors.name && theme.colors.attention} />}
error={errors.name?.message}
errors={errors}
control={control}
returnKeyType="next"
/>
I'm using react-native-phone-number-input and i want to delete the call code from the number if the user types it.
my solution is :
class PhoneUserInput extends PureComponent {
...
<PhoneInput
ref={this.myRef}
onChangeFormattedText={(value) => {
if (value.substr(`+${this.myRef.current?.getCallingCode()}`.length)
.startsWith(`+${this.myRef.current?.getCallingCode()}`)) {
value = value.substr(`+${this.myRef.current?.getCallingCode()}`.length)
.replace(`+${this.myRef.current?.getCallingCode()}`, ''));
}
onChangeFormattedText(value);
console.log('formated value'+value);
}
}}
/>
}
I tried to the same thing on onChangeText props but it's doesn't give the effect instantly on the component.
Please try to do your work with
onChangeText={ (_text)=>{ //Your code} }
AND add :
value={value}
Here is a working example :
<PhoneInput
ref={phoneInput}
defaultValue={value}
value={value}
defaultCode="FR"
layout="first"
placeholder={label}
containerStyle={styles.phoneContainer}
onChangeText={(text) => {
setValue(text)
}}
onChangeFormattedText={(text) => {
setFormattedValue(text)
}}
withDarkTheme
withShadow
/>
I'm using react-native-testing-library on a react-native-elements Input component. The component shows the clear button while editing.
How can I tap the clear button to test the side effects?
This doesn't work:
const addressField = component.getByPlaceholder("Address");
addressField.clear();
// TypeError: addressField.clear is not a function
You can use the clear option.
handleSearchClear = () => {
this.setState({ query: "" })
}
....
<Input
placeholder='BASIC INPUT'
onClear={this.handleSearchClear}
value={this.state.query}
/>
OR You can use ref
this.input.clear();
...
<Input
placeholder='BASIC INPUT'
ref={ref => {this.input = ref;}}
value={this.state.query}
/>
The event doesn't work in React-Native.
This is textInput.
<TextInput
id="name"
placeholder="name"
onChange = {this._inputChange}
/>
And This is the onChage function.
when i check with console.log(e.nativeEvent.id) writing in TextInput, it says undefined.
I guess that e.target.id can't use in React-native not React.
Could you recommend some idea?
_inputChange = (e) => {
let nextState = {};
console.log(e.nativeEvent.id)
nextState[e.nativeEvent.id] = e.nativeEvent.value;
this.setState(nextState);
}
This is how I handle this...
handleChange = (field, value) ={
this.setState({ [field]: value });
}
<TextInput
onChangeText={this.handleChange.bind(this, 'name')}
...
/>
I am creating react-native mobile app. I have an array with some values. I want to set array's value into input field. I have added value in the fields but i can't able to update these values. I have set my values in a qty variable like this:
constructor(props) {
super(props);
this.state = {
qty:[],
}
}
componentWillMount() {
var ids = [];
this.props.data.map((dataImage,Index) => {
dataImage['pro-name'] != undefined && (
ids.push({'qty':dataImage['pro-qty']})
)
})
this.setState({qty:ids})
}
render() {
return {
this.props.data.map((dataImage,Index)=>(
<View key={Index} style={productStyle.cartview}>
{dataImage['pro-name'] && (
<View style={productStyle.cartmain}>
<Input value={this.state.qty[Index]['qty']} onChange={this.handleChangeInput.bind(this)} style={{width:40,height:40,textAlign:'left'}} />
</View>
)}
</View>
))
}
}
Its showing values properly into the input field but i can't able to type anything into the field to update the values. what can i do for this
I will suggest you to move your input container into separate class, its better approach and each component will handle its own state. Its easy to handle and will result better in performance too.
components = []
render() {
return this.props.data.map((item, index) => (
<CustomComponent data={item} index={index} ref={(ref) => this.components[index] = ref} />
))
}
You can then get child (CustomComponent) value from its ref.
this.components[index].getValue()
this.components[index].setValue('Value');
You will need to create these functions (getValue & setValue) in CustomComponent class.
solution
Here is solution to your query. You need to install lodash or find other solution to make a new copy qty.
<Input onChangeText={(text) => this.handleChangeText(text, index)} />
handleChangeText = (text, index) => {
const qty = _.cloneDeep(this.state.qty);
qty[index] = {
qty: text
}
this.setState({qty})
}
Your Input's value is set to this.state.qty[Index]['qty']. And to change it on text edit, you can do it like this. You do not need to bind the function, instead use an arrow function like this.
onChangeText={ (newValue) => {
this.setState({ <your-input-value-state>:newValue })
}}
You have to update the value of each Input individually on onChange event.
Replace your with Input with this
<Input value={this.state.qty[Index]['qty']}
onChange={this.handleChangeInput.bind(this, Index)}
style={{width:40,height:40,textAlign:'left'}}
/>
and update the state accordingly with the Index when the event is called
handleChangeInput(index, value){
let {qty} = this.state;
let qty_update = qty.slice();
qty_update[index]['qty'] = value;
this.setState({qty: qty_update});
}