In React Native, only TextInput
has onFocus
and onBlur
event listener. However, we would like to simulate this effect on a View
.
Here is what we try to achieve. There is a View
on the screen. It gains "focus" when user taps on it and is hightlighted. We want to detect that user taps outside the View
, so that we can "blur" the View
, that is, remove the highlight.
I know we can use focus
method (https://facebook.github.io/react-native/docs/nativemethodsmixin.html#focus) to request focus for the View
. The problem is that I don't know how to detect that user presses outside the View
.
The onFocus event occurs when an element or some element inside it gets focus. The onBlur event is the opposite of the onFocus event. It occurs when an element (or some element inside it) loses focus. Both of these events work on all elements in the React DOM but are most often used with form.
The onBlur event is the opposite of the onFocus event. It occurs when an element (or some element inside it) loses focus. Both of these events work on all elements in the React DOM but are most often used with form.
The FocusEvent interface is used for onFocus and onBlur events. We typed the events as React.FocusEvent<HTMLElement> because the FocusEvent type is used for onFocus and onBlur events in React. However, we could have been more specific when typing the event.
This enables us to render something conditionally based on whether the user is on the screen or not. The useIsFocused hook will cause our component to re-render when we focus and unfocus a screen.
In situations like this, I add onPress()
to the the element that is outside of the View
in question.
<View onPress(removeHighlight)></View>
<View onPress(addHighlight)></View>
I think the easiest is to set a state variable instead so you can play with that one such as:
class MyView extends Component {
constructor(props) {
super(props);
this.state = {
activeView: null,
}
this.views = [
(<View style={{ padding: 20 }}><Text>View 1</Text></View>),
(<View style={{ padding: 20 }}><Text>View 2</Text></View>),
(<View style={{ padding: 20 }}><Text>View 3</Text></View>),
(<View style={{ padding: 20 }}><Text>View 4</Text></View>),
(<View style={{ padding: 20 }}><Text>View 5</Text></View>),
];
}
_setActive( index ) {
return () => {
this.setState({ activeView: index })
}
}
render() {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
{this.views.map( (view, index) => {
let containerStyle = [];
if ( index === this.state.activeView ) {
containerStyle.push({ borderWidth: 10 })
}
return (
<TouchableOpacity onPress={this._setActive(index)} style={containerStyle}>
{view}
</TouchableOpacity>
);
})}
</View>
);
}
}
You can use MyView
where requried as <MyView />
also every item on the array views
can have any style required and configure each if is active just by access to this.state.activeView
.
Let me know if you have any question.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With