Working through the Redux AddTodo example in React Native. The first AddTodo example below uses state to store the TextInput value and works fine.
class AddTodo extends React.Component{
constructor(props){
super(props);
this.state = { todoText: "" };
}
update(e){
if(this.state.todoText.trim()) this.props.dispatch(addTodo(this.state.todoText));
this.setState({todoText: "" });
}
render(){
return(
<TextInput
value = {this.state.todoText}
onSubmitEditing = { (e)=> { this.update(e); } }
onChangeText = { (text) => {this.setState({todoText: text}) } } />
);
}
}
However following a few of the Redux examples, the following code is much shorter and also works except that the TextInput value is not cleared after submitting
let AddTodo = ({ dispatch }) => {
return (
<TextInput
onSubmitEditing = { e => { dispatch(addTodo(e.nativeEvent.text)) } }
/>
)
}
Is there any way I can clear the InputText value from onSubmitEditing?
Add ref to your TextInput, for example:
<TextInput ref={input => { this.textInput = input }} />
then call this.textInput.clear() to clear your input value
For iOS, it will give the default clear text button.
<TextInput clearButtonMode="always" />
See the doc
According to changes and recommendations after React 16.3, you will need to retrieve the ref at your constructor using React.createRef:
At constructor function:
this.myTextInput = React.createRef();
At render function:
<TextInput ref={this.myTextInput} />
And then you can call
this.myTextInput.current.clear();
[1] https://reactjs.org/docs/refs-and-the-dom.html
I am using Native base
and here is how i have made it work
constructor(props) {
super(props);
this.searchInput = React.createRef();
}
<Input
placeholder="Search"
ref={this.searchInput}
/>
then whenever i want to clear i use
this.searchInput.current._root.clear();
reference https://github.com/facebook/react-native/issues/18843
One simpler approach will be to use the value property of TextInput and use the component's state value object to set the value of textInput.
state = {
inputTextValue : '',
}
submitText = () => {
//handle the click action
//add this line at the end of the function after you are done handling with the input text value.
this.setState({inputTextValue : ''})
}
<TextInput
onChangeText={(text) => this.setState({ inputText: text })}
placeholder="Monday's breakfast"
value={this.state.inputTextValue}
/>
<TouchableOpacity
onPress={() => this.submitText()}>
<Text>Submit</Text>
</TouchableOpacity>
Because you're using a functional component you can use Hooks as follows. If you have conditional renders your code check that todoInput is defined in the function passed to useEffect. I assumed your state variable is called todoText in the dependency list.
import {useRef, useEffect} from 'react';
let AddTodo = ({ dispatch }) => {
const todoInput = useRef();
useEffect(()=>todoInput.current.clear(),[todoText]);
return (
<TextInput
ref={todoInput}
onSubmitEditing = { e => { dispatch(addTodo(e.nativeEvent.text)) } }
/>
)
}
this works for me
ref={element => {
//Clear text after Input
this.attendee = element
}}
onSubmitEditing={this.handleAddPress}
and
this.attendee.setNativeProps({ text: '' }) //Clear text after Input
React-Native Using Input component from native-base.
This worked for me:
<Input ref={input => {this.textInput = input;}}
and then:
this.textInput._root.clear();
Note: Did not have to use React.createRef() to initialise.
Following code sample:
<TextInput
onChangeText={(text) => this.onChangeText(text)}
ref={component => this._textInput = component}
onSubmitEditing={() => {
this.clearText()
}}
/>
clearText(){
this._textInput.setNativeProps({ text: ' ' });
setTimeout(() => {
this._textInput.setNativeProps({ text: '' });
},3);
}
This worked for me..
Init myTextInput at the constructor:
this.myTextInput = React.createRef();
Add the reference at render function:
<Input ref={this.myTextInput} />
And then you can call
this.myTextInput.current.value='';
On my functional Component , I call another function along with submitHandler , that function will take care to clear text
const [text, setText] = useState('');
const anotherFunc = (val) =>{
setText('');
}
return (
<View>
<TextInput
value ={text}
onChangeText ={changeHander}
placeholder = 'Add '
/>
<Button
title = "Add Something "
onPress = {()=> {submitHandler(text) , anotherFunc(text)}}
/>
</View>
)
Thanks #André Abboud by your help i was able to clear my TextInput field but according to my custom TextInput, i made a slight change in implementantion.
Please review the code and approach used for implementation. As far as i know now my requirement of clearing the TextInput as i needed is fullfilled and if required for any changes please notify in comment.
And what i did to make it work is:
In setupSender.js
...
this.state = {
clearInput: false,
...
}
...
setupSenderSubmit = () => {
...
this.setState({
clearInput: !this.state.clearInput,
})
...
}
...
<CustomTextInput
labelText="First Name"
onChangeText={(firstName) => this.setState({ firstName })}
clearInput={this.state.clearInput}
value={this.state.firstName}
returnKeyType={ 'next' }
autoFocus={true}
onSubmitEditing={() => this.input2.current.focus()}
></CustomTextInput>
...
And in CustomTextInput.js
this.state={
clearInput: this.props.clearInput,
}
...
static getDerivedStateFromProps = (props, state) => {
if (props.clearInput !== '' || props.clearInput !== undefined) {
return {
clearInput: props.clearInput
}
}
return null;
}
...
<TextInput
label={this.props.label}
value={!this.state.clearInput ? this.state.text : null}
onChangeText={(text) => {
this.setState({text});
this.props.onChangeText(text)
}
}
</TextInput>
...
I make this code for clearing TextInput in React Native OnSubmitEditing
you can check my snack:
https://snack.expo.io/#andreh111/clear-textinput-onsubmitediting
Here is the code:
state = {
searchInput:'',
clearInput:false
}
render(){
return(
<View style={{flex:1,justifyContent:'center',alignItems:'center'}}>
<TextInput
style={{
borderColor:'black',
borderWidth:1,
width:200,
height:50
}}
onChangeText={(searchInput)=>this.setState({
searchInput
})}
value={!this.state.clearInput ? this.state.searchInput : null}
onSubmitEditing={()=>{
this.setState({
clearInput:!this.state.clearInput,
})
}}
/>
</View>
)
}
<TextInput
ref={input => { this.name = input }}
/>
this.name.clear();
this.email.clear();
this.password.clear();
this.confirmPassword.clear();
this.state = {
commentMsg: '',
}
after submittion
if (response.success)
{
this.commentMsg.clear(); //TODO me
}
<TextInput
style={styles.textInput}
multiline={true}
ref={input => {
this.commentMsg = input
}}
onChangeText={(text) => this.setState({commentMsg: text})}
placeholder ='Comment'/>
Work to me...
<TextInput
ref={ref => {
this.textInput = ref;
}}
...
/>
after call function
clearMsg(){
this.textInput.state.value = ''
}
Also you can set the value of the <TextInput/> the same of the state and after use the data, set the state back to an empty string:
//state
const [state, setState] = useState({
name: '',
lastname: ''
})
//functions
const newUser = () => {
// Do your magic and after
setState({
name: '',
lastname: ''
})
}
const handleOnChange = () => {
setState({
// change your state
})
}
//render
<TextInput
value={state.name}
placeholder='Name'
onChangeText={/* execute your handleOnChange() */}
/>
<TextInput
value={state.lastname}
placeholder='Lastname'
onChangeText={/* execute your handleOnChange() */}
/>
<Button title='Saved' onPress={() => newUser()} />
Hope to be usefull!
Just for a recently answer, I'm using RN CLI 0.70.6 and React 18.1.0. I'm not using EXPO
const input = useRef(null)
<TextInput
ref={input}
onSubmitEditing={e => {
//do something here e.g. console.log(e.nativeEvent.text)
input.current.clear();
}
/>
The trigger is gonna be when you press the "Enter" it's gonna redirect you or do whatever you specified and also clear the current input.
for RN > 0.6
const [msg, setMsg] = useState()
use value inside TextInput
<TextInput
onChangeText={(txt) => setMsg(txt)}}
value={msg}
/>
then set state in your button press function like this
const pressButton = () => {
setMsg('')
}
Related
i am using map function to render my component which have textInput . I want to change value of textInput using onchangeText function.
//main component
const [Value0, setValue0] = useState('');
const [Value1, setValue1] = useState('');
const [Value2, setValue2] = useState('');
..
const handleOnSubmit = () => { //fired when click from this
compnent button
console.log(Value0,"Value0");
console.log(Value1,"Value1");
}
//in my return i use :
{
data.map((item, id) => {
return (
<ViewDeatilCard1 key={id} /> //data having length 4
)
})
}
<ViewDeatilCard1 key={id} setChangeText={(value)=>{`'setValue${id}${(value)}'`}} /> //this
<ViewDeatilCard1 key={id} setChangeText={()=>{`'setValue${id}'`}} /> //this
<ViewDeatilCard1 key={id} setChangeText={`'setValue${id}'`} /> //this
// none of this work
// in my component i use
export const ViewDeatilCard1 = ({
setChangeText
}) => {
console.log(setChangeText,"setChangeText");
return (
<View style={styles.container}>
<View style={styles.body}>
<FormInput
style={styles.bodyText}
labelText="Enter pick up loaction"
iconName="null"
onChangeText={setChangeText}
/>
</View>
</View>
)}
how can i change my value using this approach
I have a TextInput and I don't want it to re render every time I change the value inside it
const [WrittenVal,setWrittenVal] = useState(()=>'');
...
<TextInput
value={String(WrittenVal)}
onChangeText={text => setWrittenVal(text)}
/>
but I want to be able to change the value inside the input at the push of a button that's why I haven't just used defaultValue
any solutions??
You can use useRef to save text from text input without render , and useState to show text in input on button press:
Live example : https://snack.expo.dev/TW-fMx1-2
import React from "react";
import { SafeAreaView, StyleSheet, TextInput,TouchableOpacity,Text } from "react-native";
const UselessTextInput = () => {
const [text, onChangeText] = React.useState("");
const textRef = React.useRef('')
const textToRef = (text) =>{
textRef.current = textRef.current + text
}
const showTextInInput = () =>{
onChangeText( textRef.current )
}
console.log("render")
return (
<SafeAreaView>
<TextInput
style={styles.input}
onChangeText={textToRef}
value={text}
/>
<TouchableOpacity onPress={showTextInInput}>
<Text>SHOW TEXT IN INPUT</Text>
</TouchableOpacity>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
input: {
height: 40,
margin: 12,
borderWidth: 1,
marginTop:50,
padding: 10,
},
});
export default UselessTextInput;
const inputRef = useRef();
<TextInput
ref={inputRef}
onChangeText={text => inputRef.text = text }
/>
//function to get input value
const handleSubmit = () => {
let textInputValue = inputRef.text;
}
You cannot prevent re-renders on type. But your code can be simplified to:
const [value, setValue] = useState('');
<TextInput
value={value}
onChangeText={setValue}
/>
You can't prevent re-render on input when the value change.
But you can prevent other components to be re-renderd by React.memo or useMemo hook.
And for changing value of input with button press you can do like this:
<Button onPress={() => {
setWrittenVal(""); //write value you want in ""
}}
If you have a nested component situation like the below you need to move the state into the component (under EpicComponent) the setWrittenVal will trigger a re-render on the EpicComponent. Common symptoms are the the field will lose focus when you type.
const Parent = ()=> {
const [WrittenVal,setWrittenVal] = useState(()=>'');
...
const EpicComponent = ()=> {
return (
<TextInput
value={String(WrittenVal)}
onChangeText={text => setWrittenVal(text)}
/> )
}
return (<EpicComponent/>)
}
I'm in react native app an I use typeScript too.
I have a functional component :
const Input: React.FunctionComponent<IInputProps> = ({
inputStyle,
placeHolderColor = EAppColors.DARK_GREY,
placeHolder,
value,
onChangeText,
autoFocus,
onFocus,
onBlur,
onSubmitEditing,
ref,
keyboardType = EKeyboardType.DEFAULT,
}) => {
return (
<StyledInput
testID="TextInputID"
placeholderTextColor={placeHolderColor}
placeholder={placeHolder}
...
I create some ref for different input before my render:
const firstNameRef = React.createRef<TextInput>();
const lastNameRef = React.createRef<TextInput>();
const birthDateRef = React.createRef<TextInput>();
and I use after this component in a class like that :
<StyledTextInput
label={I18n.t('auth.heading.firstNameLabel')}
errorText={errorText}
ref={firstNameRef}
autoFocus={true}
placeHolder={I18n.t('auth.placeHolder.firstName')}
isFocused={focusOnFirstFields}
hasError={hasError}
onFocus={() => this.setState({ focusOnFirstFields: true })}
onBlur={() => this.setState({ focusOnFirstFields: false })}
showClearButton={showFirstClearButton}
value={firstName}
onClearText={() => this.onClearText(1)}
onChangeText={(value: string) =>
this.setState({
firstName: value,
disabled: false,
showFirstClearButton: true,
})
}
onSubmitEditing={() => {
if (lastNameRef !== null && lastNameRef.current !== null) {
lastNameRef.current.focus();
}
}}
keyboardType={EKeyboardType.DEFAULT}
/>
But when I want to use onSubmitEditing for focus the next input, I have this error :
How can I resolve this issue ?
Thank You!
Like this:
const FancyButton = React.forwardRef</* type of ref*/HTMLButtonElement, /* component props */ComponentProps>((props, ref) => (
<button ref={ref} className="FancyButton">
{props.children}
</button>))
It will be correctly typed as
const FancyButton: React.ForwardRefExoticComponent<React.RefAttributes<HTMLButtonElement>>
(You don't need to use React.FunctionComponent when using forwardRef).
const Input = React.forwardRef<TextInput, IInputProps>(({
inputStyle,
placeHolderColor = EAppColors.DARK_GREY,
placeHolder,
value,
onChangeText,
autoFocus,
onFocus,
onBlur,
onSubmitEditing,
keyboardType = EKeyboardType.DEFAULT,
}, ref /* <--- ref is passed here!!*/) => {
// assuming this is a TextInput
return (
<StyledInput
ref={ref}
testID="TextInputID"
placeholderTextColor={placeHolderColor}
placeholder={placeHolder}
...
})
I faced a similar problem a few months ago. I solved it by doing:
import {TextInputProps, TextInput} from 'react-native';
type IProps = TextInputProps & {
labelText?: string;
};
const TextInputStd: React.FC<IProps> = React.forwardRef(
(
{
labelText,
...textInputProps
}: IProps,
ref: React.Ref<TextInput>,
) => {
const {styles} = useStyles(_styles);
return (
<>
<View style={[styles.textInputContainer, styles2.textInputContainer]}>
<Text style={styles.labelText}>{labelText || ''}</Text>
<View style={styles.inputWrapper}>
<TextInput style={styles.input} {...textInputProps} ref={ref} />
</View>
</View>
</>
);
},
);
Hope this gives you an idea.
not 100% sure what the question is here, but
<StyledInput
ref={ref}
testID="TextInputID"
placeholderTextColor={placeHolderColor}
placeholder={placeHolder}
...
should work, then you need to pass the ref in when calling this input.
Guys I was using the Material-UI text-field and made some custom theme options by by making it as a custom component .
Like Below :-
const CustomTextField = ({props}) =>{
return (
<TexField
label={props.label}
name={props.label}
value={props.row[props.label]}
onChange={(e)=>props.handleChangeFunction(e)}
/>
)
}
In My Component I inject like below :-
const App = () =>{
const [value,setValue] = useState('');
//Some methods here
const handleChange = () =>{
//Logic here.......
}
return(
<>
<CustomTextField {...{label:'name',row:emp,handleChangeFun:handleChange}}/> //Custom Comps...
</>
)
}
So What happens on each input my component renders and the cursor jumps out off the text field so for the next value to input I have to click the text field again.
But when I use the normal text field , directly in the component it works fine , I understand it is because of the onChange Event and using text field in a custom component .
On each value change the parent compoenent re-renders .
So what will be the solution can anyone give me a solution ?
I'm not sure about your way of passing props. This should work:
const CustomTextField = (props) => {
return (
<TextField
label={props.label}
name={props.label}
value={props.value}
onChange={props.onChange}
/>
);
};
export default function App() {
const [value, setValue] = useState("");
const handleChange = (e) => {
setValue(e.target.value);
};
return (
<>
<CustomTextField label="name" value={value} onChange={handleChange} />
</>
);
}
Optionally you can create your component like this, without grouping props:
const CustomTextField = ({label, value, onChange}) => {
return <TextField label={label} name={label} value={value} onChange={onChange}/>
};
According to this link in the React Native API Documents:
https://facebook.github.io/react-native/docs/0.59/textinput#isfocused
The TextInput component has a method called isFocused(). How would I go about accessing this method? Do I have to use a ref?
Also, I already know that I can achieve the same effect by using the onFocus prop and setting up a state manager and a function to change the state of the input based on the onFocus. However, I am just curious how I would go about using these component methods since there are others in other components as well.
I have tried using this
<TextInput onChangeText={this.handleText} style={(this.isFocused()) ? styles.input : styles.lame} placeholder="Names"/>
but it is looking like I might have to use a ref since it seems that it isn't defined even though the method should be a part of this component.
isFocused() should be called on ref to TextInput.
import React, {useEffect, useRef} from 'react';
import {TextInput, BackHandler} from 'react-native';
function SearchBar() {
const textInputReference = useRef(null);
useEffect(() => {
let backhandler = BackHandler.addEventListener(
'hardwareBackPress',
function() {
if (textInputReference.current.isFocused()) {
textInputReference.current.blur();
return true;
}
return false;
},
);
return () => {
backhandler.remove();
};
}, []);
return (
<TextInput ref={textInputReference} />
);
}
export default SearchBar;
You can use state for handle input focus, if you have multi-input that also need focus state, just create many state for it.
class MyComponent extends React.Component {
state = { isFocused: false }
handleInputFocus = () => this.setState({ isFocused: true })
handleInputBlur = () => this.setState({ isFocused: false })
render() {
const { isFocused } = this.state
return (
<View>
<TextInput
onFocus={this.handleInputFocus}
onBlur={this.handleInputBlur}
style={ isFocused ? styles.input : styles.lame}
/>
<Text>Hello World</Text>
</View>
)
}
}
This another easy way to use the onFocus prop in TextInput
import React, { useState } from 'react'
import { View, StyleSheet, TextInput } from 'react-native'
const TextInput = () => {
const [isHighlighted, setIsHighlighted] = useState(false)
return (
<View>
<TextInput
style={[styles.textInput, isHighlighted && styles.isHighlighted]}
onFocus={() => { setIsHighlighted(true)}
onBlur={() => {setIsHighlighted(false)} />
</View>
)
}
const styles = StyleSheet.create({
textInput: {
borderColor: 'grey',
borderWidth: StyleSheet.hairlineWidth,
borderRadius: 8,
height: 43,
},
isHighlighted: {
borderColor: 'green',
}
})
According to its documentation
Returns true if the input is currently focused; false otherwise.
How we can achieve that? the answer is useRef.
For example :
import React, { useRef } from 'react'
import { View, StyleSheet, TextInput, Button } from 'react-native'
const App = props => {
const inputRef = useRef(null);
const checkIsFocusedHandler = () => {
const result = inputRef.current.isFocused();
alert(result);
}
return (
<View style={styles.container}>
<TextInput ref={inputRef} style={styles.input} value="Abolfazl Roshanzamir" />
<TextInput style={styles.input} />
<Button title="Check isFocused" onPress={checkIsFocusedHandler} />
</View>
)
}
If we click on the first TextInput then click on the button, the result is => true,
if we click on the second TextInput then click on the button, the result is => false.
Use onFocus props of TextInput component
<TextInput onFocus={yourCallBack} />
yourCallBack function will be called when the TextInput is focused