I recently tried using the Drawer component of Native Base 2.0 which basically has this template:
closeDrawer = () => {
this.drawer._root.close()
};
openDrawer = () => {
this.drawer._root.open()
};
render() {
return (
<Drawer
ref={(ref) => { this.drawer = ref; }}
content={<SideBar navigator={this._navigator} />}
onClose={() => this.closeDrawer()} >
<Content>
insert content here
</Content>
</Drawer>
)
}
I made my customer SideBar component with some ListItems in there, I made those list items clickable using the react-navigation package.
onPress={() => this.props.navigation.navigate(data)}>
The problem is that I don't get the this._navigator property that is being passed from the Side Bar and I always get this error:
NativeBase has deprecated Drawer, use react-navigation instead
They have added back Drawer in v2.8.0
https://github.com/GeekyAnts/NativeBase/releases/tag/v2.8.0
Related
I'm using React Navigation on React Native, how do I swipe between multiple screens?
I can only find an onPress solution that navigates me to a specific screen on button press, but I would like to just swipe left and right as well.
Your help would be super appreciated
I think you are willing to create a slider between screens
I think you can use react-native-snap-carousel
import Carousel from 'react-native-snap-carousel';
export class MyCarousel extends Component {
_renderItem = ({item, index}) => {
return (
<View style={styles.slide}>
<Text style={styles.title}>{ item.title }</Text>
</View>
);
}
render () {
return (
<Carousel
ref={(c) => { this._carousel = c; }}
data={this.state.entries}
renderItem={this._renderItem}
sliderWidth={sliderWidth}
itemWidth={itemWidth}
/>
);
}
}
Currently I have:
return(
<View style={{flex: 1, paddingTop:20}}>
<FlatList
data={this.state.dataSource}
renderItem={(data) => <EventCard eventinfo = {data.item} navigation=
{this.props.navigation}/>}
keyExtractor={(item) => item.eventname}
/>
and
const EventCard = ({eventinfo, navigation}) => {
return (
<TouchableOpacity style={{backgroundColor: 'transparent'}} onPress= {()
=> navigation.navigate('CurrRes')}>
I dont understand why Navigation cant be evaluated in my Eventcard, and navigation doesnt work. Any help would be appreciated.
(yes withnavigation is imported in the first file and the project runs but crashes when one of the flatlist items is pressed)
The error i get is
undefined is not an object (evaluating 'navigation.navigate')
Here is an example I found to explain it better.
You need to access props differently than just a normal function with deconstruction.
const Child = (props) => {
return (
<div style={{backgroundColor: props.eyeColor}} />
)
}
https://medium.com/#PhilipAndrews/react-how-to-access-props-in-a-functional-component-6bd4200b9e0b
Nevermind, I had to export the actual list with navigation so each of its nested stateless components could navigate. Sorry!
I am trying to build a Chat Application using react-native and using flatlist to display the messages. And i want my list to stay at bottom always can anyone plzz suggest me a solution.
Basically you need to use scrollToEnd on flatList..
First: create a flatList reference with:
ref={ (ref) => { this.myFlatListRef = ref } }
Second: add onContentSizeChange listener on flatList
onContentSizeChange={ () => { this.myFlatListRef.scrollToEnd({animated:true}) } }
Third: add onLayout listener on flatList for scroll to bottom when keyboard is showed.
onLayout={ () => { this.myFlatListRef.scrollToEnd({animated:true}) } }
eg:
<FlatList
ref={ (ref) => { this.myFlatListRef = ref } }
onContentSizeChange={ () => { this.myFlatListRef.scrollToEnd({animated:true}) } }
onLayout={ () => { this.myFlatListRef.scrollToEnd({animated:true}) } }
data={this.state.messages}
renderItem={ ({item}) => <Item data={item} /> }
/>
the simplest way to do this is to use inverted props in the flatlist
this allow us to render list up-side-down
for more ref. vidit https://facebook.github.io/react-native/docs/flatlist#inverted
Here, you can do this -
const messageData = this.props.convo
return (
<View style={{ flex: 1 }}>
<FlatList
inverted={-1}
style={styles.list}
extraData={this.props}
data={messageData}
keyExtractor = {(item) => {
return item.id;
}}
renderItem=
{this.renderItem}
/>
after that, you will get an inverted list which will have the topmost elements in the list, so for fixing this you can add reverse() in your flatlist data or in your reducer. Like this-
data={messageData.reverse()} or in reducer return { ...state, chats: action.payload.reverse() }
You can give a refto FlatList and access certain flatList properties that can scroll at particular position. Here below resolution should work.
setTimeout(() => this.refs.flatList.scrollToEnd(), 200)
ScrollToEnd React native
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
I have a webview as tab A and a todolist flatlist on tab B. If the user adds an entry to the flatlist on tab B, i want the tab A webview to refresh.
I couldn't find any .refresh() or reload() methods on the webview control https://facebook.github.io/react-native/docs/webview.html
Any ideas how to accomplish this?
You can set a key to the webview
key={this.state.key}
and then you can reload it by updating the state
this.setState({ key: this.state.key + 1 });
Well I reload WebView by doing following:
render() {
let WebViewRef;
return (
<View style={Style1.container}>
<WebView
ref={WEBVIEW_REF => (WebViewRef = WEBVIEW_REF)}
source={{ uri: this.state.site }}
renderLoading={this.ActivityIndicatorLoadingView}
startInLoadingState={true}
/>
<Button title="Reload Me!" onpress={() => { WebViewRef && WebViewRef.reload(); }} />
</View>
)
}
In this code I Declare Reference Variable WebViewRef first then assign this to WebView as ref={WEBVIEW_REF => (WebViewRef = WEBVIEW_REF)} and then call this reference for reload() as ()=>{ WebViewRef && WebViewRef.reload();}
The react-native-community/react-native-webview component has a .reload() method on the ref.
const webViewRef = useRef();
// ...
return (
<WebView ref={(ref) => webViewRef.current = ref} ... />
)
// ...
You can then use the following to reload:
webViewRef.current.reload();
I ended up using a dummy query parameter to signal a refresh of the web view:
In Tab B, I dispatch a change which changes "latestItemId" in the global state.
In Tab A, I use mapStateToProps which maps to <WebView source={{uri:URL?latestItemId=${latestItemId}}} /> in the render method. This causes it to think it's a new url and reload it.
Reload was not working on my end.
If you want to refresh on focus change you can use the hook useFocusEffect of react navigation and in the unmount clean the URL used in the webview. Then in the initialize you need to set that again. Maybe using a a useState.
useFocusEffect(
useCallback(() => {
setUrl(url!);
return () => {
setUrl(undefined);
};
}, [url]),
);
In my case I have source={{html}} so refresh() won't work in that situation. However, in my case I am still able to inject javascript so I can set some properties specifically document.styles.body.color to match dark and light mode.
const fg = colorScheme === "light" ? "black" : "white";
const webViewRef = createRef<WebView>();
useEffect(() => {
webViewRef.current?.injectJavaScript(`
document.body.style.color='${fg}';
true
`);
}, [fg]);
...
<WebView
ref={webViewRef}
originWhitelist={["*"]}
style={{
height: 200,
backgroundColor: "transparent",
}}
onMessage={() => {}}
javaScriptEnabled={true}
injectedJavaScript={`
document.body.style.color='${fg}';
true;`}
source={{ html }}
/>