I'm writing an application and only want the back button to show when I push new views onto the Navigator (in this case a news article vs. a list of news articles).
It seems like the way to do this would be to modify render() to only include the Back button for certain navigator states. And while the React Native docs suggest components inside the navigator can access it using getContext, this doesn't seem to work for navigatorBar.
Is this the right way to go about it? How would I render the Back button only for certain navigation states?
<Navigator
initialRoute={{name: 'NewsList', index: 0}}
renderScene={this.renderScene}
sceneStyle={styles.navigator}
navigationBar={
<View style={styles.navbar}>
<View style={styles.logo_container}>
<Text style={styles.backButton}>Back</Text>
<Image
source={require( 'image!Logo' )}
style={styles.logo}
/>
</View>
<View style={styles.separator} />
</View>
}
/>
It will help to move your navigationBar code into its own component, pass the route information into it*, then check for route depth.
TLDR;
if (route.index > 0){
//Show Back Button.
}
Or just make your life easier and user either of these plugins to do the job for you.
React-Native-NavBar https://github.com/Kureev/react-native-navbar
React-Native-Router https://github.com/t4t5/react-native-router
*Passing the route may no longer be needed since the addition of Navigator.getContext(this).xxx was added. See navigator documentation for further info on getContext https://facebook.github.io/react-native/docs/navigator.html
Related
I have a GeoJSON data of lakes and rivers. I am displaying them using the code below.
<MapView.Geojson
geojson={barajVeGolet}
strokeColor="#39A2DB"
fillColor="#D0E8F2"
strokeWidth={3}
/>
This component renders the data in the map like the image below.
MapView.Geojson Component display example
I want a popup to appear when a user clicks anywhere inside this lake, like a marker.
What I have tried:
I wrapped MapView.Geojson with TouchableOpacity component, to use
its onPress attribute.
<TouchableOpacity onPress={onPress}>
<MapView.Geojson
geojson={barajVeGolet}
strokeColor="#39A2DB"
fillColor="#D0E8F2"
strokeWidth={3}
></MapView.Geojson>
</TouchableOpacity>
I used onPress attribute of the MapView.Geojson
<MapView.Geojson
geojson={barajVeGolet}
strokeColor="#39A2DB"
fillColor="#D0E8F2"
strokeWidth={3}
onPress={onPress}
></MapView.Geojson>
I put a Callout component inside the MapView.Geojson with text
<MapView.Geojson
geojson={barajVeGolet}
strokeColor="#39A2DB"
fillColor="#D0E8F2"
strokeWidth={3}
>
<MapView.Callout>
<View style={{ width: 200 }}>
<Text style={styles.barajInfoTitle}>Test</Text>
</View>
</MapView.Callout>
</MapView.Geojson>
Is there any way to click anywhere inside a Geojson or Polygon component which opens a popup, just like the Marker component?
Unfortunately, you cannot set custom callout while using GeoJson of the its Marker module does not supporting it.
https://github.com/react-native-maps/react-native-maps/blob/master/lib/components/Geojson.js#L156
However, you can use custom solution for this use-case.
I've added the onPress functionality for GeoJson
<Geojson
tappable
image={require("assets/markers/bicycle/seasonal-tour.png")}
geojson={your-data}
strokeColor={colors.theme.light.routeColor}
strokeWidth={7}
onPress={(data: any) => {
this.props.myInfoModal.openModal(); // For Modalize
this.setState({modalVisibility: true }); // For Classic Modal
}}
/>
You can use classic modal or modalize
https://github.com/react-native-modal/react-native-modal
https://github.com/jeremybarbet/react-native-modalize
Then you can show the data detail into
I'd like to create a basic "setting toggle" component, with Title and Subtitle on the left, and a Switch on the right. I'd like to be able to switch the toggle when the whole component is clicked, not just when the switch is.
In order to achieve this is wrapped the component in a Touchable and execute the supplied onValueChange callback, so the container component can handle the state change of the switch.
export default function SettingToggle({
title,
subtitle,
toggled,
onValueChange,
}) {
return (
<TouchableWithoutFeedback
style={styles.container}
onPress={() => onValueChange(!toggled)}
>
<View>
<Text style={styles.title}>{title}</Text>
<Text style={styles.subtitle}>{subtitle}</Text>
</View>
<Switch
value={toggled}
onValueChange={value => onValueChange(value)}
></Switch>
</TouchableWithoutFeedback>
)
}
Now when I click the Switch, it animates nicely to the other value, but when click the component, the whole component redrawn with the new value of {toggled}, thus on the UI it feels like the switch is instantly changing to the other value.
Question 1: How could I preserve the animation even when the component is clicked, and not just the Switch?
Question 2: From where does React know, that it doesn't need to redraw the view when only the Switch is clicked? The render() method is called, as the parent component's state changes with the onValueChange call, so the SettingToggle is rerendered with a new {toggled} value. I assume the view is "recreated" but under the hood React probably isn't changing the view in the hierarchy with the newly created one, as it somehow knows that it is not needed. How does this work?
I have created a custom button component that should respond to touches. It works as expected on iOS, however on Android it doesn't show up at all. While trying to find the cause of this issue.
I created two snacks on expo to demonstrate the issue. The first is the element wrapped in a Touchable element, and the second is the element without it.
In the first snack, it works as expected in iOS, however it is not shown on Android.
In the second snack, it appears as expected on both, however it is not clicking
https://snack.expo.io/#shepherdjerred/button-with-touchable
https://snack.expo.io/#shepherdjerred/button-without-touchable
For the first snack, add style={{flex: 1}} to the first view component. Flex adjusts a component based on the amount of space available in the application's screen.
return (
<TouchableWithoutFeedback onPressIn={this.handlePressIn.bind(this)}
onPressOut={this.handlePressOut.bind(this)}>
<View style={{flex: 1}}>
<View
style={[
this.stylesheet.buttonLayer,
this.stylesheet.buttonShadow
]}>
</View>
<View
style={[
this.stylesheet.buttonLayer,
this.stylesheet.buttonDepth
]}>
</View>
<View
style={[
this.stylesheet.buttonLayer,
this.stylesheet.buttonTop,
this.state.isPressed ? this.stylesheet.buttonTopPushed : this.stylesheet.buttonTopUnpushed
]}>
</View>
</View>
</TouchableWithoutFeedback>
);
}
For the second snack, the React Native website has two ways of creating buttons or components that can be touched.
References:
Facebook Inc. "Height and Width". React Native.
https://facebook.github.io/react-native/docs/height-and-width.html
(accessed April 2, 2018).
Facebook Inc. "Handling Touches". React Native.
https://facebook.github.io/react-native/docs/handling-touches.html
(accessed April 2, 2018).
https://stackoverflow.com/a/44063868/8121551 (accessed April 2,
2018).
I made a socket connected app, when a value is changed, all the other clients receive the value modification. This is supposed to lead into an automatic UI change.
Here is my code :
<View style={{marginTop:20}}>
<Slider
ref="container"
minimumValue={0}
maximumValue={100}
value={this.state.briValue}
onValueChange={val => {
this.setState({ briValue: val })
socketEmit('hue-bri', val)
}
}
/>
<Text>Brightness : {this.state.briValue} %</Text>
</View>
The result :
Issue : the slider thumb does not move
I don't know why the Slider component does not re-render while the Text component does.
I tried to force the reload with this.refs.container.forceUpdate() but it does nothing.
I use the Slider from react-native-elements and the Text component is from the original react-native library.
Any help is greatly appreciated.
value prop is only used to initialize the slider.
Ref : https://facebook.github.io/react-native/docs/slider.html#value
My list component should be able to highlight why a certain element is part of the list based on keywords entered by the user.
I am using the react-highlighter component currently inside the list item, but it requires me to send down the keyword entered by the user from the search box => to the listview => to the list item
That doesn't look very react to me.
I am also using redux so I have only one store, and the listview and items are not directly aware of the store. They are dumb components just rendering properties.
<SearchBox onChange={setSearchText} value={searchText} />
<List items={item} highlight={searchText}>
<ListItem>
<Highlight search={searchText}>{name}</Highlight>
</ListItem>
</List>
Is there a more elegant way to handle such highlighting?
As you mentioned in a comment you could pull up your highlight functionality into a HighlightedListItem component.
<SearchBox onChange={setSearchText} value={searchText} />
<List items={item} >
<HighlightedListItem item={item} highlight={searchText}>
{...stuff}
</ListItem>
</List>
In addition when thinking ahead to maximizing performance, this approach might be easier to reason when adding a shouldcomponentupdate
EX:
// HighlightedListItem
shouldComponentUpdate: function(nextProps, nextState) {
return nextProps.item !== this.props.item ||
nextProps.searchText !== this.props.searchText;
}