React Native TextInput does not get focus - react-native

I have this simple code of a TextInput that I want it to get focus when it first renders and on submits. However, it does not get focus at all.
render() {
return (
<TextInput
ref={(c) => this._input = c}
style={[styles.item, this.props.style]}
placeholder={"New Skill"}
onChangeText={(text) => {
this.setState({text})
}}
onSubmitEditing={(event) => {
this.props.onSubmitEditing(this.state.text);
this._input.clear();
this._input.focus();
}}
/>
);
}
componentDidMount() {
this._input.focus();
}

So my assumption is true. Try to focus is failed, this._input doesn't contain anything when componentDidMount called, because render function still not called yet and no reference for it.
So the solution for now is delay it a little bit until render function already called.
Thats why wrap the code inside setTimeout function quite helpful. Anyway i admit it, it is a little bit tricky. Would be great if someone find the better way.
componentDidMount() {
setTimeout(() => this._input.focus(), 250);
}

You can use autoFocus property of TextInput and set it to true. It will focus TextInput on componentDidMount automatically.I tested it and it's focusing input on both componentDidMount and onSubmitEditing.
render() {
return (
<TextInput
ref={(c) => this._input = c}
placeholder={"New Skill"}
autoFocus={true}
onChangeText={(text) => {
this.setState({text})
}}
onSubmitEditing={() => {
this.props.onSubmitEditing(this.state.text);
this._input.clear();
this._input.focus();
}}
/>
);
}

Related

react native textinput lost focus after 1 char type

I have this problem with ios but not with android. It only disturb the add task input the task edit and the list name edit. The input addList(It's the one with "What to do?" on the draw) in the header works fine.
UI drawing
Achitecture of components
I console log my component and I can see it rerender everytime I add a letter in the input field.
I checked on google and follow this:(can we link other website here?) https://www.codegrepper.com/code-examples/javascript/react+native+textinput+lost+focus+after+charter+type
Tried the the first solution with onBlurr and onFocus.
I tried to make a TextInput component for add task.
I even try with my component addList but it didn't solve the problem.
Anyone have faced this problem before? Is there anyway to by pass this?
My code without the import/style look like this:
const TaskList: FunctionComponent<TasksListProps> = ({
addTask,
deleteTask,
toggleTask,
editTaskName,
...props
}) => {
console.log('props', props);
const [nameOfTask, setNameOfTask] = useState('');
console.log('name', nameOfTask);
const textHandler = (enteredName: string) => {
setNameOfTask(enteredName);
};
const handleSubmitTask = () => {
if (nameOfTask === '') {
return;
}
addTask(props.listId, nameOfTask);
setNameOfTask('');
};
return (
<View style={styles.tasksListContainer}>
{props.tasks.map(task => (
<SingleTask
key={task.id}
task={task}
listId={props.listId}
deleteTask={deleteTask}
toggleTask={toggleTask}
editTaskName={editTaskName}
/>
))}
<View style={styles.taskInputContainer}>
<TextInput
style={styles.tasksTextInput}
value={nameOfTask}
onChangeText={textHandler}
placeholder="Write a task to do"
/>
<TouchableOpacity onPress={handleSubmitTask}>
<Image source={require('./Img/add-button.png')} />
</TouchableOpacity>
</View>
</View>
);
};
You can create a HOC and wrap your screen width DismissKeyboard
import { Keyboard } from 'react-native';
const DismissKeyboard = ({ children }) => (
<TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
{children}
</TouchableWithoutFeedback>
);
That because Re render.
Try to make the input with the main component of the page to test it.
Then check where the error with re-render

gifted-chat renderAction prop won't call a function

I'm trying to make a custom menu to share pictures and location using the renderAction prop in gifted-chat. I can't get it to call a function. renderActions={console.log('hello')} outputs as expected, for some reason functions aren't being called.
I've looked at code examples, and I can't find anything that I'm missing - but obviously I'm missing something.
here's the code. If there's any extra info that would be helpful, please let me know and I'll add it. Still new to stack.
renderActions > console.log() doesn't get called
renderActions() {
console.log('renderActions called');
}
renderAction={console.log()} get's called.
renderActions={this.renderActions} does not get called.
I've tried passing it in every way I can think of:
{() = > this.renderActions()}, {this.renderActions.bind(this)}, {this.renderActions} ... nothing seems to work.
render() {
let bgColor = this.props.route.params.bgColor;
return (
<View style={[styles.bodyContent]}>
<GiftedChat
renderBubble={this.renderBubble.bind(this)}
renderSystemMessage={this.renderSystemMessage.bind(this)}
renderInputToolbar={this.renderInputToolbar.bind(this)}
renderActions={() => this.renderActions()}
messages={this.state.messages}
onSend={(messages) => this.addMessage(messages)}
user={{
_id: this.state.uid,
}}
/>
{Platform.OS === 'android' ? (
<KeyboardAvoidingView behavior="height" />
) : null}
</View>
);
}
Any help would be greatly appreciated. I'm sure I'm missing something obvious, but I'm completely stumped. Thank you!
render action is not supposed to console log, if you see what it returns you will see it returns JSX
import {GiftedChat, InputToolbar} from 'react-native-gifted-chat';
// custom action
const customAction = () => {
return(
<View>
<Text>Custom Action</Text>
</View>
);
}
<GiftedChat
renderInputToolbar={props => {
return (
<InputToolbar
{...props}
containerStyle={styles.chatWithoutBorder}
renderComposer={() => <CustomComposer {...props} />}
renderActions={ <CustomAction /> }
renderSend={() => <CustomSend {...props} />}
/>
);
}}
/>
all these custom components are actually normal components you can create it on your own, all you need is to send props for it
and for the footer below the message box, you will need this renderAccessory as described here in the https://github.com/FaridSafi/react-native-gifted-chat
Thanks to my tutor, I have an answer!
The renderInputToolbar={} prop overwrites renderActions={}. I ended up not using the renderActions prop in the <GiftedChat /> component. Instead passing it as a prop to the <InputToolbar />.
Here's the code:
` <GiftedChat
renderBubble={this.renderBubble.bind(this)}
renderSystemMessage={this.renderSystemMessage.bind(this)}
renderInputToolbar={this.renderInputToolbar.bind(this)}
//renderActions={this.renderActions.bind(this)}
messages={this.state.messages}
onSend={(messages) => this.addMessage(messages)}
user={{
_id: this.state.uid,
}}
/>`
Then the renderInputToolbar method:
renderInputToolbar() {
if (this.state.onlineStatus == false) {
} else {
return <InputToolbar renderActions={this.renderActions} />;
}
}

React Native TextInput ref always undefined

I have a simple TextInput that I want to put a reference on in my render:
<View>
<TextInput ref={(component) => this._inputElement = component}>Input</TextInput>
{console.log(this._inputElement)}
<Button
onPress={this.addAddress}
title="Submit"
color="#841584"
/>
</View>
I want to then use that ref in a function above that is bound in my contructor:
constructor(props) {
super(props);
this.state = {
addresses: []
};
this.addAddress = this.addAddress.bind(this);
}
addAddress function:
addAddress(event, result) {
console.log("reference:", this._inputElement.value);
}
The console log in both the render and addAddress are always undefined.
I have looked around but no one seems to be having my problem, usually they have a typo or didn't bind the function they then want to call.
Why do I seem unable to have references?
Using State
Usually the way to use TextInput is to store the value in state.
Remember to initialize the address in your state as an empty string, otherwise having a null value for address could cause an error.
constructor(props) {
super(props)
this.state = {
....
address: ''
}
}
Then you could define your text input as follows
<TextInput
onChangeText={address => this.setState({address})}
value={this.state.address}
/>
Then in your addAddress
addAddress(event, result) {
console.log("reference:", this.state.address);
}
Using Refs
Alternatively you could use ._lastNativeText to access it from the reference
<TextInput
ref={ref => { this._inputElement = ref }}>
Input
</TextInput>
then in your addAddress
addAddress(event, result) {
// I always check to make sure that the ref exists
if (this._inputElement) {
console.log("reference:", this._inputElement._lastNativeText);
}
}
I wouldn't recommend the second method as you are accessing private methods that could be liable to change in a future release.
Textinput self-encloses
<View>
<TextInput ref={ref=> (this._inputElement = ref)}/>
<Button
onPress={this.addAddress}
title="Submit"
color="#841584"
/>
</View>
addAddress(event, result) {
console.log("reference:", this._inputElement._lastNativeText); //this get's the value, otherwise it's undefined
}
This snippet works properly in react native and react native web:
const txtRef = useRef(null)
return(
<TextInput
ref={txtRef}
onChangeText={text => txtRef.current.value = text}
/>
<Button
title='log and reset'
onPress={() => {
console.log(txtRef.current.value)
txtRef.current.clear()
txtRef.current.value = ''
}}
/>
)
`

React-Native re-render Flatlist

I'm having trouble keeping the data in my Flatlist after coming back from another page. My scenario is as follows:
User goes to homepage and scrolls through 20 items
User clicks their profile tab changing page using react-native-router-flux
User clicks the home tab taking them back to the list however the list re-renders and starts from the top.
How can I stop this re-rendering and fetching the same data again?
componentDidMount() {
this.makeRemoteRequest();
}
makeRemoteReuest gets my data from firebase in batches of 5 and sets data: []
data: [...this.state.data, ...results]
I've tried using the below but not sure if this is correct, when i navigate away and back the data re-renders. I want to keep the data so the page will be exactly the same as when it was left.
shouldComponentUpdate(nextProps, nextState) {
if (JSON.stringify(this.state.data) !== JSON.stringify(nextState.data)) {
return true;
}
return false;
}
My flatlist:
<View>
<FlatList
scrollsToTop={false}
ref={(ref) => { this.flatListRef = ref; }}
showsHorizontalScrollIndicator={false}
onScroll={this.handleScroll}
data={this.state.data}
keyExtractor={item => item.key}
ListFooterComponent={this.renderFooter()}
onRefresh={this.handleRefresh}
refreshing={this.state.newRefresh}
onEndReached={this.handleEndRefresh}
onEndReachedThreshold={0.05}
getItemLayout={this.getItemLayout}
renderItem={this.renderItem}
/>
{this.state.refreshAvailable ? this.renderRefreshButton() : null}
</View>
Thanks for any help!
Coded long back for the dumb project, maybe this can help you
The View: used onLayout Prop for getting the y-axis
<ScrollView
ref={(ref) => this.scrollTo = ref}
contentContainerStyle={{margin:5,}}
>
<Card onLayout={(event) => this._findHeight(event.nativeEvent.layout, 'personal')}>
<Personal review={true}/>
</Card>
</ScrollView>
The Function: stored the y-axis; here i have used realm db
_findHeight = (e, name) => {
const {x, y, width, height} = e;
this.realm.write(() => {
this.realm.create('yLocation',{names:name,yaxis:y}) :
});
}
The AutoScroll Method: here i have used scrollTo method from ScrollView you can use any method using their ref
_scrollTo = (y) => {
this.scrollTo.scrollTo({x:0,y:y,animated:true});
}
Note : Call _scrollTo method in componentDidMount

React Native Touchable on press down event

I'm trying to create a component similar to TouchableHighlight, but instead of highlighting the background I want to highlight text. I need to hook into the onPress event that fires at the point the user actually presses.
I've tried using TouchableWithoutFeedback and onPressIn, but it doesn't seem to fire. Here is the code I've been testing with.
class TouchableTextHighlight extends React.Component {
constructor (props) {
super(props)
this.state = {
isHighlighted: false
}
}
highlight () {
console.log('pressed')
this.setState({
isHighlighted: true
})
}
render () {
let textColor = this.state.isHighlighted ? '#F44336' : null
return (
<TouchableWithoutFeedback {...this.props} onPressIn={() => {this.highlight}} onPress={this.props.onPress}>
<View {...this.props}>
<Text
style={[this.props.textStyle, {color: textColor}]}
>{this.props.text}</Text>
</View>
</TouchableWithoutFeedback>
)
}
}
You need to invoke the method. Change:
onPressIn={() => {this.highlight}}
to
onPressIn={() => {this.highlight()}}
Your code is perfectly fine but you missed one thing which is very important to understand- Binding functions. Yourhighlight function not bound to the context. There are many ways to bind the function but here I will tell about one way which is efficient.
highlight () {
console.log('pressed')
this.setState({
isHighlighted: true
})
}
rewrite above function like this
highlight = () => {
console.log('pressed')
this.setState({
isHighlighted: true
})
}
If you want to read more about binding in react check out here