I use react navigation TabNavigator and I want every time user goes to second tab, one TextInput in screen get focus and keyboard gets popup
You can use refs and react navigation lifecycle for this:
constructor(props) {
super(props);
this.input = React.createRef();
this.didFocusDSubscription = this.props.navigation.addListener(
'didFocus',
payload => {
this.input.current.focus();
}
);
}
render() {
return <TextInput ref={this.input} />;
}
this might help you
this.viewDidAppearListener = this.props.navigation.addListener('didFocus', (payload) => this._viewDidAppear(payload));
didFocus event will be triggered every time the view is showed (like viewDidAppear in iOS) so you can then do focus() on your textinput manually.
Simplest is to add "autoFocus" to your textInput
Like this:
<TextInput
placeholder="Type any activity name"
placeholderTextColor="lightgray"
...
ref="textInput"
autoFocus />
For react-navigation#3.X.X use navigation.addListener and .focus():
class AutoFocusedTextInput extends React.Component {
state = {
text: '',
}
componentDidMount() {
this.props.navigation.addListener('didFocus', payload => {this.textInput.focus()})
}
componentWillUnmount() {
didFocusSubscription.remove();
}
render() {
return (
<View>
<TextInput
ref={(component) => this.textInput = component}
autoFocus={true}
placeholder="Start typing"
onChangeText={(text) => this.setState({text})}
value={this.state.text}
/>
</View>
)
}
}
The reference:
https://reactnavigation.org/docs/3.x/navigation-prop#addlistener---subscribe-to-updates-to-navigation-lifecycle
Related
The configuration is as follows:
class MyComponent extends Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
...
render() {
...
<TextInput style={styles.textInput}
...
ref={this.inputRef}
/>
...
}
}
Q. How to find out if TextInput has focus within a render() method?
you can check either by using this functions or by creating your custom setup by registering onBlur() and onFocus() callback functions in your textInput.
e.g.
<TextInput
onFocus={() =>console.log("focus received" ) }
onBlur={() => console.log("focus lost") } />
NetInfo is used to check the connection & theres a checkNetwork function called in onPress of TouchableOpacity. When the button is clicked once, the checkNetwork
function is called automatically multiple times without tapping the button when the network connection is lost and vice versa.
Please have a look at the code here:
Please have a look at the video
export default class App extends React.Component {
checkNetwork = () => {
NetInfo.addEventListener((state) => {
if (state.isConnected) {
alert('isConnected');
} else {
alert('not connected');
}
});
};
render() {
return (
<View style={styles.container}>
<TouchableOpacity
activeOpacity={0.8}
onPress={()=> this.checkNetwork()}>
<Text>Check here</Text>
</TouchableOpacity>
</View>
);
}
}
You should not declare event listener inside of the click itself,
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {alert: ''};
}
componentDidMount() {
NetInfo.addEventListener((state) => this.setState({ alert: state.isConnected ? 'isConnected' : 'not connected'})
}
checkNetwork = () => alert(this.state.alert)
render() {
return (
<View style={styles.container}>
<TouchableOpacity
activeOpacity={0.8}
onPress={()=> this.checkNetwork()}>
<Text>Check here</Text>
</TouchableOpacity>
</View>
);
}
}
though in your case event listener isn't exactly the fit logic for UI behavior of pressing button, so I think you might wanna use useNetInfo
import {useNetInfo} from "#react-native-community/netinfo";
class App extends React.Component {
checkNetwork = () => {
if (this.props.netInfo.isConnected) {
alert('isConnected');
} else {
alert('not connected');
}
});
};
...rest render...
}
export default () => <App netInfo={useNetInfo()} />
There was no issue before I tried to implement the handleInputBlur and handleInputFocus functions (Used to change the background when in focus). When I first click on the TextInput it comes into focus, but then immediately blurs, resulting in the background flashing then disappearing. What's strange is that after this first click, the future clicks work absolutely fine, focusses and blurs as it should. I do not understand why on the initial click/focus it immediately blurs. Code below:
EDIT: Bit more context, it's inside of a modal, which contains multiple of these editable items.
class EditableItem extends Component {
constructor(props) {
super(props)
const { value } = this.props
this.state = {
value,
isFocused: null,
}
}
handleInputBlur = () => {
this.setState({ isFocused: false })
console.log('blurring')
}
handleInputFocus = () => {
this.setState({ isFocused: true })
console.log('focussing')
}
render() {
const { name, secure, children, autoCapitalize } = this.props
const { value, isFocused } = this.state
const multiline = !secure
return (
<View>
<View style={styles.container}>
<Text style={styles.name}>{name}</Text>
<View style={isFocused ? styles.activeBackground : styles.unfocusedBackground}>
<TextInput
placeholder={name}
placeholderTextColor={COLOR_BASE_3}
underlineColorAndroid="transparent"
style={styles.value}
secureTextEntry={secure}
value={value}
// blurOnSubmit
onSubmitEditing={() => {
Keyboard.dismiss()
}}
returnKeyType="done"
keyboardAppearance="dark"
autoCapitalize={autoCapitalize}
onChangeText={this.onChange}
multiline={multiline}
onBlur={() => this.handleInputBlur()}
onFocus={() => this.handleInputFocus()}
/>
{children}
</View>
</View>
<View style={styles.divider} />
</View>
)
}
onChange = value => {
const { onChange } = this.props
this.setState({ value })
onChange(value)
}
}
Ok so solved this by setting autofocus to true in the TextInput. Not sure why not having this set causes this issue but it's a solution regardless.
I am facing problem getting reference of TextInput which is defined in static navigationOptions, it's that any way to do it in React Native? i am sharing some code here so you better know about my questions.
export default class SearchClass extends React.Component {
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state;
let headerTitle = (
<View style={{flex: 1}}>
<TextInput
style={{ flex: 1, height: 30 }}
placeholder='Search'
keyboardType='default'
returnKeyType='search'
underlineColorAndroid='transparent'
onChangeText={text => params.onChangeText(text)}
onSubmitEditing={(event) => { params.onSearchButton()
}}
/>
</View>
);
return { headerTitle };
};
componentDidMount() {
this.props.navigation.setParams({
onChangeText: this.__onChangeSearchText,
onSearchButton: this.__onSearchButtonPress
});
}
__onSearchButtonPress = () => {
// clear the text of TextInput
// for that i need reference here of TextInput
this.mySearchBox.clear();
}
}
_onSearchButtonPress i need to clear the text of TextInput, for that i need reference of that TextInput which is define in navigationOptions ?
does anyone know how to do it?
I've added a static variable inside class
static textField = null;
and then assign it inside navigationOptions
<TextInput
ref={(ref) => YourClass.textField = ref}
...
then when I need to pass events (not sure if that's the best way) I either do a pubsub-js listener and publish event or I forward events - both ways explained with code bellow.
<TextInput
ref={(ref) => YourClass.textField = ref}
onChangeText={(text) => {
YourClass.textField.onChangeText(text);
// PubSub.publish(Constants.FIELD_DID_CHANGE, [text,]);
}}
then when didFocus -- viewDidAppear equivalent
let textField = YourClass.textField;
textField.onChangeText = (text) => this._textFieldDidChange(text);
or register PubSub object in componentDidMount
// this.textFieldDidChangeListener = PubSub.subscribe(Constants.FIELD_DID_CHANGE, (msg, data) => this._textFieldDidChange(data));
export default class TopMiddleLoadingView extends React.Component{
size = 66;
constructor(props) {
super(props);
this.state = {
fill : 99,
timeLeft : props.timeLeft
}
}
onPress(){
this.setState = {
...this.state, fill:10
}
}
componentWillUpdate(nextProps, nextState) {
alert("componentWillUpdate");
}
render(){
alert("render")
return(
<View style={{width:this.size, height:this.size}}>
<View style={[styles.absoluteCenter,{zIndex:999}]}>
<Thumbnail source={Images.seaImg}></Thumbnail>
</View>
<Text>{this.state.fill}</Text>
<Button
style={{width:50,height:50,backgroundColor:"red",position:"absolute",zIndex:999}}
onPress={this.onPress}
></Button>
</View>
);
}
}
on button press, onPress function is clicked, and change the state of the component, but the render function is not calling.
I am very new to react native. Any idea?
You aren't changing the state either let alone re render. And if you want to re render then you should change state using setState() method. Also, you need to refresh you javascript this knowledge
export default class TopMiddleLoadingView extends React.Component{
size = 66;
constructor(props) {
super(props);
this.state = {
fill : 99,
timeLeft : props.timeLeft
}
}
onPress = () => {
this.setState({fill:10})
}
componentWillUpdate(nextProps, nextState) {
alert("componentWillUpdate");
}
render(){
alert("render")
return(
<View style={{width:this.size, height:this.size}}>
<View style={[styles.absoluteCenter,{zIndex:999}]}>
<Thumbnail source={Images.seaImg}></Thumbnail>
</View>
<Text>{this.state.fill}</Text>
<Button
style={{width:50,height:50,backgroundColor:"red",position:"absolute",zIndex:999}}
onPress={this.onPress}
></Button>
</View>
);
}
}
Render method is called whenever there is change in state of that component. You should use this.setState({...this.state, fill:10} for updating state of the component. This must cause render function to fire again, if there is not any other logic written inside shouldComponentUpdate() for conditional rendering.
Hope this helps. Also check out,
What the difference of this.state and this.setstate in ReactJS?