Background
I'm developing a heatmap component in React Native which is essentially a <View> that responds to pointerEvents provided by the user. The children are extracted from this.props and passed into the view.
<View
style={s.overlay}
onLayout={this._onLayout}
onMagicTap={this._onDoubleTwoFingerTouch}
onAccessibilityTap={this._onDoubleTouchAccessible}
onStartShouldSetResponder={this._onTouchStart}
onResponderMove={this._onTouchMove}
onResponderReject={this._onTouchCancel}
onResponderTerminate={this._onTouchCancel}
onResponderRelease={this._onTouchEnd}
pointerEvents={'auto'}
>
{children}
</View>
Problem
The view receives all touch events as long as there is no touchable component (like a <TouchableOpacity> component) beneath it. Obviously then, the child component responds to the pointerEvents.
I already know how the auto, box-none, etc. pointerEvents enums operate, but I have not found the right combination or trick in order to trickle down these events from parents to children.
TL;DR
How can I respond to pointerEvents in BOTH parent and the child components on a user's press?
Related
I'm working with snackbar and a clickable layer.
For example:
Pressable Layer and Snackbar are absolute positioned siblings, the code roughly looks like this:
<>
<PressableLayer></PressableLayer>
<Snackbar></Snackbar>
</>
The problem is <Snackbar> is intercepting gestures, blocking <PressableLayer> from responding.
According to the doc, react-native's gesture respond system uses a bubbling pattern to decide who shall be responding. In this case, if <Snackbar> doesn't claim to be a responder, its parent get to respond, but I would like <PressableLayer> to respond instead.
Is there a way to achieve this?
Found an answer here
Add pointerEvents="none" to the <View> inside <Snackbar> like this:
return (<View pointerEvents="none"></View>)
I'm trying to make a transition in which given a list of preview thumbnails, when I click on one, it scales it to the complete screen with all the additional details as required. Problem I'm having is that when I try using the properties position: 'absolute', top: 0, right: 0, left: 0, zIndex: 2 in order to place the component's full view on top of all other sibling components like a modal, for some reason, the child component is only able to cover the area that it's child component is covering as a thumbnail.
Structure:
-- Parent Component containing FlatList of Child Components
-- -- Child Component 0
-- -- Child Component 1
-- -- Child Component 2
-- -- Child Component 3
-- -- Child Component 4
The idea is to make something similar to the way it works in the iOS App store: https://vimeo.com/272028619
And this is another illustration how I need it to work like: https://vimeo.com/272027050
And this is how it looks like right now: https://vimeo.com/272027061
How is it possible for me to cover the complete area of the Parent Component as a child component?
Try styling your parent component as absolute and on each onclick event of your child component, toggle the z-index.
Hope this works :)
Position absolute doesn't work well inside FlatList. You can replace your FlatList with View and set position: absolute to the View component like below:
data.map((item) =>
<View style={{position: absolute}}>
<ChildComponent item={item}>
</View>
);
Now in your child component, you have to set top property of each card which will be sum of the heights of all the previous cards. Your applied animation will work after this.
Is there a way to delay rendering of content of dropdown/modal until it is open?
I see they are being rendered even if they are not visible until user clicks to see its contents.
The Modal component uses Portal for rendering content, while Portal renders something only if it's open. This means that the component already satisfies your conditions.
With the Dropdown component, it will be more difficult. You can control it yourself, but it means that you will need to process all events self-consciously and it will be not easy.
<Dropdown open={true} options={open && options} />
All:
I am pretty new to React. What I am trying to build is a component which can detect mouse status like mousedown, mouseup, mousemove, mousedrag, mouse dblclick.
This component actually has nothing with UI, so I wonder what should I return in render function? Say I have a class like:
class MouseActionMonitor {
constructor(){
}
render(){
return (
)
}
}
And I want to use it like( it does not have to be like this, this is just my guess of its usage):
ReactDOM.render( <MouseActionMonitor><App state={state} /></MouseActionMonitor>, document.getElementById("content"));
Here the App is the actually application components, #content is a div fill the whole window. MouseActionMonitor can update certain part in the state tree to indicate current mouse action( also still wondering how to use this component to detect mouse action ).
The reason I want to do this is because I want to drage and drop item between "drag/drop-able" component(this component has a text label in it, when drag it, it will give you a copy of that text, and when u hover other component of this kind, it should allow u to drop this text and replace the one current in it)
Thanks
I'm trying to animate a MapView in React Native so that when it's pressed, it goes from being an element in a ScrollView to the map covering the entire screen (including navigation and status bars).
For the overlay view I'm using react-native-overlay
I've got it sort of working by:
measuring the map position with UIManager.measure
activating the overlay and rendering the same map but now inside an overlay
positioning the map relative to the overlay based on measurement
animating the map size to cover the entire screen
The problem is that when going to/from overlay, the entire map reloads which effectively kills the magic of the animation.
From what I understand, since I move the MapView pretty far in the VDOM tree, React kills it and inits a new one. I've tried to avoid this by passing the MapView as a prop to the component doing the animation. My idea was that since the prop is not be changed, the MapView shouldn't be re-instantiated. Unfortunately this doesn't help..
I also tried wrapping the MapView in another component and having shouldComponentUpdate always returning false. Doesn't help either..
Is there someway I can prevent the MapView from re-initializing when I move it in the render tree?
My render tree looks like this:
var map = <MapView />;
When map in ScrollView:
<ScrollView>
...some other content...
{map}
</ScrollView>
when in Overlay:
<ScrollView>
...some other content..
<Overlay isVisible={true} aboveStatusBar={true}>
<View style={styles.fullScreen}>
<Animated.View style={[styles.mapContainer,{top: this.state.topValue, height: this.state.heightValue}]}>
{map}
</Animated.View>
</View>
</Overlay>
</ScrollView>
I believe you should add key property to the Map component. This is the only way to tell React that the particular components in two rendering passes are the same component in fact, so it will reorder the component rather than destroy/recreate. Without key, if the component moves in the tree, react will always destroy/recreate it as it does not know that it's actually the same component (there is nothing that could tell react it is). The key property works in lists/arrays but I think it should also work for more complex tree rearrangements.
See more details here: https://facebook.github.io/react/docs/multiple-components.html#dynamic-children
Note that the link above is for react.js not react-native, but I believe it should work in exactly the same way. I found that there are quite many concepts/details not explained in react-native tutorial, but they are clear in the react.js one (for example explanation about ref property). Actually the authors assume that you have experience with react (so I went on and learned React.js as well ;):
From https://facebook.github.io/react-native/docs/tutorial.html#content :
We assume you have experience writing websites with React. If not,
you can learn about it on the React website.