how to change header title in react native functional component? - javascript

i am using react-navigation v4 and i want to change the title and the approach i am using is slow while rendering(title that is set in the stack navigator is rendered first and then new one is rendered),is there better way i can render only the new one
export default NewsList = ({ results, navigation}) => {
return <View >
<FlatList
data={results}
keyExtractor={result => result.id}
renderItem={({ item }) => {
return (
<TouchableOpacity
onPress={() => navigation.navigate( 'news',title: item.title)}>
<NewsCard result={item} />
</TouchableOpacity>)
}}
/>
</View>
};
////////////////////////////////////////////////////////////////////
export default NewsScreen = ({ navigation}) => {
NewsScreen.navigationOptions = {
title: navigation.getParam("title");,
};
}
////////////////////////////////////////////////////////////////////
const NewsStack = createStackNavigator({
NewsList :NewsList,
News :NewsScreen
},{
initialRouteName:'NewsList',
defaultNavigationOptions: {
headerStyle: {
backgroundColor: '#4BB5C3',
},
},
navigationOptions: {
tabBarLabel: 'NewsList',
},
});
export default createAppContainer(NewsStack);

Ciao, try to set title before navigate into NewsList like this:
export default NewsList = ({ results, navigation}) => {
return <View >
<FlatList
data={results}
keyExtractor={result => result.id}
renderItem={({ item }) => {
return (
<TouchableOpacity
onPress={() => {
navigation.setParams({ otherParam: item.title });
navigation.navigate('news');
}
}>
<NewsCard result={item} />
</TouchableOpacity>)
}}
/>
</View>
};
And I think you could remove navigationOptions in NewsScreen.

Related

undefinded is not an object

Hello I'm facing with render error in my movie app during printing results for movie searching. Im working in React-Native 0.70.5. Here is some code for this activity
`
import React,{useState,useEffect} from 'react';
import axios from 'axios';
import { View, StyleSheet, Text, TextInput,ScrollView } from "react-native";
const Search = () => {
const apiurl="https://api.themoviedb.org/3/search/movie?api_key=XXX"
const [state,setState] = useState({
s: "Enter a movie",
results:[]
});
const search = () => {
axios(apiurl + "&query="+ state.s).then(({ data }) => {
let results = data.search;
console.log(data);
setState(prevState => {
return{...prevState, results: results }
})
})
}
return (
<View>
<TextInput
onChangeText={text => setState(prevState => {
return {...prevState, s:text}
})}
onSubmitEditing={search}
value={state.s}
/>
<ScrollView>
{state.results.map(result =>(
<View key={result.id}>
<Text>{result.title}</Text>
</View>
))}
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
center: {
flex: 1,
justifyContent: "center",
alignItems: "center",
textAlign: "center",
},
});
export default Search;
`
How to change the construction of this function to print movie titles corectly ?
This is just an example and not the best way to do it.
You need a success flag, something like this:
const [success,setSuccess] = useState(false);
const search = () => {
axios(apiurl + "&query="+ state.s).then(({ data }) => {
let results = data.results;
console.log(data);
setState(prevState => {
return{...prevState, results: results }
})
setSuccess(true);
})
}
<ScrollView>
{success && state.results.map(result =>(
<View key={result.id}>
<Text>{result.title}</Text>
</View>
))}
</ScrollView>
I am not sure but you can try this below ScrollView code...
<ScrollView>
{state.results.length>0 && (state.results.map((result) =>(
<View key={result.id}>
<Text>{result.title}</Text>
</View>
)))}
</ScrollView>
use optional chaining. Might be sometimes you don't get result.
<ScrollView>
{state?.results?.map(result =>(
<View key={result?.id}>
<Text>{result?.title}</Text>
</View>
))}
</ScrollView>
Let me know is it helpful or not

React native SectionList is not showing data from firebase

I am fetching an array of two objects. there are "title" and "iqtiboslar" array inside objects. and show it in SectionList but it is giving an error: "can not read properties of undefined(reading 'length')". Here is my code. Any ideas will be highly appreciated
const Item = ({iqtiboslar}) => (
<View>
<Text>{iqtiboslar}</Text>
</View>
);
const HomeScreen = ({navigation}) => { const [quote, setQuote] = useState();
useEffect(() => {
fetchQuotes();
return () => {
setQuote();
};
}, []);
const fetchQuotes = async () => {
try {
const quoteCollection = await firestore().collection('iqtiboslar').get(); // get(:field) to get specific doc
quoteCollection._docs.map(doc => setQuote(doc.data().items));
// quoteCollection._docs.map(doc => console.log(doc));
} catch (error) {
console.log(error);
}
};
return (
<View style={styles.container}>
{quote ? (
<SectionList
sections={quote}
keyExtractor={(item, index) => item + index}
renderItem={({item}) => <Item title={item.title} />}
renderSectionHeader={({section}) => <Text>{section.title}</Text>}
/>
) : (
<ActivityIndicator />
)} </View>
);
};
export default HomeScreen;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
text: {
color: 'red',
},
});
Try this code
<SectionList
sections={quote}
keyExtractor={(item, index) => item + index}
renderItem={({item}) => <Text>{item}</Text>}
renderSectionHeader={({section: {title}}) => (
<Text style={styles.text}>{title}</Text>
)}

React Native - React Navigation Tab Bar - Custom floating action button

I need some help to use React Native - react navigation library.
It is Tab bar, but the Upload button acted as floating action button.
I have try :
const click = () => {
console.log('click');
return (
<View>
<Text>a</Text>
</View>
);
};
tabBarOnPress: (tab) => {
click();
},
// Main Page Navigator
export const Main = TabNavigator({
Home: {
screen: HomeNavigator,
},
Explore: {
screen: ExploreNavigator,
},
Upload: {
screen: UploadMain,
navigationOptions: ({ navigation }) => ({
tabBarLabel: 'Upload',
tabBarIcon: ({ tintColor }) => (
<View>
<Icon name="camera" size={26} color={tintColor} />
</View>
),
tabBarOnPress: (tab) => {
click();
},
}),
},
}, {
tabBarComponent: TabBarBottom,
tabBarPosition: 'bottom',
backBehavior: 'none',
swipeEnabled: false,
lazy: true,
animationEnabled: false,
showIcon: true,
tabBarOptions: {
activeTintColor: 'black',
},
});
The Upload button is need to act as floating action button, when it clicked, it already logging, but not rendering the component.
Any workaround to create the floating action button?
I've some tricks like this https://github.com/react-navigation/react-navigation/pull/1335
But, it is only click and dispatch navigation, not doing floating action button
Regards,
Charlie
you should write this code to your component!
-- you can use ‘react-native-tab-navigator' --
import TabNavigator from 'react-native-tab-navigator';
...
render(){
// console.log('TabRouter this.state:',this.state);
let tabs = [<Home {...this.props}/>,<Chat {...this.props}/>,<Web {...this.props}/>,<User {...this.props}/>];
let a = this.state.loginData.tabList.map((item,key)=>{
// console.log('item:',item);
return(
<TabNavigator.Item
key={key}
selected={this.state.selectedTab === item.type}
title={item.name}
renderIcon={() => <Image source={{uri:item.iconUnselectedUrl}} style={{width:24,height:24,}}/>}
renderSelectedIcon={() => <Image source={{uri:item.iconSelectedUrl}} style={{width:24,height:24}} />}
badgeText={this.state.tabBadge}
onPress={() => this.setState({
selectedTab: item.type,
tabBadge:0,
})}
>
{tabs[key]}
</TabNavigator.Item>
)
});
// console.log('a:',a);
return(
<TabNavigator
hidesTabTouch={true}
sceneStyle={{backgroundColor:'#fff'}}>
{a[0]}
{a[1]}
<TouchableOpacity
key={'add'}
style={{}}
renderIcon={() => <View style={{borderRadius:5,backgroundColor:'#46aee3',
width:width/5,height:49,justifyContent:'center',alignItems:'center'}}>
<Text style={{fontSize:49,padding:0,color:'#ffffff',backgroundColor:'rgba(0,0,0,0)'}}>+</Text></View>}
onPress={()=>this.props.navigation.navigate('SendBlog')}
/>
{a[2]}
{a[3]}
</TabNavigator>
)
}
...
-- update 2018/01/22 --
I think you should
let that;
class UploadMain extends Component {
constructor(props){
super(props);
that = this;
this.state = {
change:false,
};
}
changeState = () => {
this.setState({change:!change});
};
navigationOptions: ({ navigation }) => ({
tabBarLabel: 'Upload',
tabBarIcon: ({ tintColor }) => (
<View>
{that.state.change ? <Text>loading...</Text>:<Icon name="camera" size={26} color={tintColor} />}
</View>
),
tabBarOnPress: () => {
that.changeState;
},
}),
render(){
return (
<View>
....
</View>
)
}
}
If you are using react-navigation version 5.x, you should use tabBarButton to modify.
the code detail you can read
https://medium.com/#my.maithi/react-native-navigation-add-custom-button-in-the-middle-of-tabbar-6c390201a2bb
Hope can help you.

Implement pull to refresh FlatList

please help me out to implement pull to refresh on my app, I'm kinda new to react native, thanks. I don't know how to handle onRefresh and refreshing.
class HomeScreen extends Component {
state = { refreshing: false }
_renderItem = ({ item }) => <ImageGrid item={item} />
_handleRefresh = () => {
};
render() {
const { data } = this.props;
if (data.loading) {
return (
<Root>
<Loading size="large" />
</Root>
)
}
return (
<Root>
<HomeHeader />
<FlatList
contentContainerStyle={{ alignSelf: 'stretch' }}
data={data.getPosts}
keyExtractor={item => item._id}
renderItem={this._renderItem}
numColumns={3}
refreshing={this.state.refreshing}
onRefresh={this._handleRefresh}
/>
</Root>
);
}
}
export default graphql(GET_POSTS_QUERY)(HomeScreen);
Set variable
this.state = {
isFetching: false,
}
Create Refresh function
onRefresh() {
this.setState({isFetching: true,},() => {this.getApiData();});
}
And in last set onRefresh and refreshing in FlatList.
<FlatList
data={ this.state.FlatListItems }
onRefresh={() => this.onRefresh()}
refreshing={this.state.isFetching}
/>
After fetching Data in function getApiData Make sure to set false isFetching.
this.setState({ isFetching: false })
You can also use refreshControl in Flatlist, ScrollView, and any other list component.
<FlatList
contentContainerStyle={{ alignSelf: 'stretch' }}
data={data.getPosts}
keyExtractor={(item) => item._id}
renderItem={this._renderItem}
numColumns={3}
refreshControl={
<RefreshControl
refreshing={this.state.refreshing}
onRefresh={this._handleRefresh}
/>
}
/>
If someone is interested in doing it with React Hooks here is it:
First create isRefreshing state:
const [isRefreshing, setIsRefreshing] = useState(false)
Then create your onRefresh function that calls API to refresh data:
const onRefresh = () => {
//set isRefreshing to true
setIsRefreshing(true)
callApiMethod()
// and set isRefreshing to false at the end of your callApiMethod()
}
And after that, your FlatList component that looks like that:
return (
<FlatList
style={styles.flatList}
onRefresh={onRefresh}
refreshing={isRefreshing}
data={data}
renderItem={renderItem}
keyExtractor={item => item.id.toString()}
/>
)
// Sample code representing pull to refresh in flatlist. Modify accordingly.
import React, { Component } from 'react'
import { Text, View,StyleSheet,FlatList,Dimensions,Image,TouchableHighlight } from 'react-native'
export default class Home extends Component {
constructor(props)
{
super(props);
this.state = {
data : [],
gender : "",
isFetching: false,
}
}
componentWillMount()
{
this.searchRandomUser()
}
onRefresh() {
this.setState({ isFetching: true }, function() { this.searchRandomUser() });
}
searchRandomUser = async () =>
{
const RandomAPI = await fetch('https://randomuser.me/api/?results=20')
const APIValue = await RandomAPI.json();
const APIResults = APIValue.results
console.log(APIResults[0].email);
this.setState({
data:APIResults,
isFetching: false
})
}
render() {
return (
<View style = {styles.container}>
<TouchableHighlight
onPressOut = {this.searchRandomUser}
style = {{width:deviceWidth - 32, height:45,backgroundColor: 'green',justifyContent:"center",alignContent:"center"}}>
<Text style = {{fontSize:22,color: 'white',fontWeight: 'bold',textAlign:"center"}}>Reload Data</Text>
</TouchableHighlight>
<FlatList
data={this.state.data}
onRefresh={() => this.onRefresh()}
refreshing={this.state.isFetching}
keyExtractor = { (item, index) => index.toString() }
renderItem={({item}) =>
<View style = {styles.ContainerView}>
<View>
<Image
source={{uri : item.picture.large}}
style = {{height:100,width:100,borderRadius: 50,marginLeft: 4}}
resizeMode='contain'
/>
</View>
<View style = {{flexDirection: 'column',marginLeft:16,marginRight: 16,flexWrap:'wrap',alignSelf:"center",width: deviceWidth-160}}>
<Text>Email Id : {item.email}</Text>
<Text>Full Name : {this.state.gender} {item.name.first} {item.name.last}</Text>
<Text>Date of birth : {item.dob.age}</Text>
<Text>Phone number : {item.phone}</Text>
</View>
</View>
}
/>
</View>
)
}
}
const deviceWidth = Dimensions.get('window').width
const deviceHeight = Dimensions.get('window').height
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
marginTop:22
},
ContainerView:
{
// backgroundColor:'grey',
marginBottom:20,
paddingVertical:10,
backgroundColor: '#F5F5F5',
borderBottomWidth:0.5,
borderBottomColor:'grey',
width: deviceWidth-40,
marginLeft:20,
marginRight:20,
marginTop:20,
flexDirection:'row'
}
});
const [refreshing, setRefreshing] = useState(false)
<FlatList
style={{ padding: 15 }}
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={_onRefresh}
tintColor="#F8852D"/>
}
showsVerticalScrollIndicator={false}
data={listData}
renderItem={renderItem}
item={(item, index) => index.toStirng()}
onEndReachedThreshold={0.8}
onEndReached={() => onEndReached()}
ListFooterComponent={() => renderFooter()}
/>
_onRefresh Function
const _onRefresh = () => {
console.log('_onRefresh')
setRefreshing(true);
getPosts();
};
"Pull to refresh" concept implies that the list can be manually refreshed thus can be changed outside the current view (e.g. fetched from server). So the callback onRefresh has to trigger the data reloading process (e.g. send a request to the server) and set the refreshing variable to truthy value. This will notify the user that the process was started by showing loading indicator. Once you got the data ready you need to set refreshing to falsy so the view will hide loading indicator.
this is the best that I can do. my Code Image
when I pull it down it dosen't refetch data from server I'm running graphql server which connected by Apollo to the app, and I don't know how to get data from server in _getData() function.
Instead of using pull to refresh on flat-list simply use on Scroll View.
Set Refresh State
this.state = {
isFetching: false,
}
Set onFresh in ScrollView
<ScrollView
refreshControl={
<RefreshControl
refreshing={this.state.refresh}
onRefresh={() => this.onRefresh()}
tintColor="red"
/>
}>
<FlatList data={data} renderItem={this._renderItem} numColumns={3} />
</ScrollView>;
In OnRefreshFunction
onRefresh() {
this.setState({refresh: true});
setTimeout(() => {
this.setState({refresh: false});
}, 2000);
}
You can check the official document:
https://reactnative.dev/docs/refreshcontrol
For anyone looking for an updated answer using new React Hooks.
You can use isLoading and refetch from useQuery.
Then use RefreshControl with FlatList. Read more on RefreshControl: https://reactnative.dev/docs/refreshcontrol
const RenderImageGrid = (item) => <ImageGrid item={item} />
export const HomeScreen = () => {
const { data, isLoading, refetch } = useQuery('get_home_screen_data', GET_HOME_SCREEN_DATA)
return (
{isLoading ? (
<Root>
<Loading size="large" />
</Root>
) : (
<Root>
<HomeHeader />
<FlatList
data={data}
keyExtractor={item => item._id}
renderItem={RenderImageGrid}
numColumns={3}
refreshControl={
<RefreshControl
refreshing={isLoading}
onRefresh={refetch}
/>
}
/>
</Root>
)}
)
}
export default HomeScreen

align navscreen content in react-native

I am very new to react-native. I am trying to create a drawer using react-navigation. I could use DrawerNavigator but could not show the header/navbar on all the screens. That is why i create a NavScreen component with profile icon, title and back icon. However they are not aligned properly. I need profile icon to be shown on the left side, title on the center and back button on the right side. How can i do this?
Here is my code
const styles = StyleSheet.create({
container: {
marginTop: Platform.OS === 'ios' ? 20 : 10,
},
});
const NavScreen = ({ navigation, banner }) => (
<ScrollView style={styles.container}>
<Text>{banner}</Text>
<Icon
name="ios-contact-outline"
size={30}
color="#000"
onPress={() => navigation.navigate('DrawerOpen')}
/>
<Icon
name="ios-arrow-round-back-outline"
size={30}
color="#000"
onPress={() => navigation.goBack(null)}
/>
</ScrollView>
);
export default NavScreen;
class App extends React.Component {
static navigationOptions = ({ navigation }) => ({
title: `${navigation.state.routeName}`,
drawerTitle: `${navigation.state.routeName}`,
drawerLabel: 'Home',
drawerIcon: ({ whiteColor }) => (
<MaterialIcons name="drafts" size={14} style={{ color: whiteColor }} />
),
})
render() {
const { navigation } = this.props;
return (
<ScrollView>
<NavScreen navigation={navigation} banner={'Main'} />
<Text>Main Screen</Text>
</ScrollView>
);
}
}
export default App;
I need similar to the below image
First, try to build a StackNavigation, at headerRight, and headerLeft you define your custom buttons (the above), now you can very easy customize the align/padding whatever you need with your icons/buttons.
const stackNavigatorConfiguration = {
// set first Screen
initialRouteName: 'Home',
mode: Platform.OS === 'ios' ? 'card' : 'card',
navigationOptions: ({navigation}) => ({
headerRight: <DrawerButton navigation={navigation} />,
headerLeft: <YourProfileButton navigation={navigation} />,
headerBackTitle: null
})
}
const YourProfileButton = ({ navigation }) => (
<TouchableOpacity>
<Ionicons
style={styles.profileButton}
name='ios-menu-outline'
size={32}
onPress={() => navigation.goBack(null)}
/>
</TouchableOpacity>
)
const DrawerButton = ({ navigation }) => (
<TouchableOpacity>
<Ionicons
style={styles.drawerIcon}
name='ios-menu-outline'
size={32}
onPress={() => navigation.navigate('DrawerOpen')}
/>
</TouchableOpacity>
)

Categories

Resources