I have simple app, with 3 tabs. Tabs are defined by TabBarIOS in index.ios. I’m not using Navigator nor NavigatorIOS. In each TabBarItem , I just put the component name in tags. Like this :
return(
<TabBarIOS
selectedTab={this.state.selectedTab}
//unselectedTintColor="yellow"
//tintColor="white"
//barTintColor="darkslateblue"
>
<TabBarIOS.Item
icon={{uri: 'courses.png', scale: 5}}
title="Courses"
badge={undefined}
selected={this.state.selectedTab === 'courses'}
onPress={() => {
this.setState({
selectedTab: 'courses',
});
}}>
<Courses />
</TabBarIOS.Item>
<TabBarIOS.Item
icon={{uri: 'register.png', scale: 5}}
title="Register"
badge={undefined}
selected={this.state.selectedTab === 'register'}
onPress={() => {
this.setState({
selectedTab: 'register',
});
}}>
<NavigatorIOS
//style={styles.nav}
initialRoute={{
title : 'Register',
component: Register
}}
/>
</TabBarIOS.Item>
<TabBarIOS.Item
icon={{uri: 'profile.png', scale: 5}}
title="Profile"
badge={undefined}
selected={this.state.selectedTab === 'profile'}
onPress={() => {
this.setState({
selectedTab: 'profile',
});
}}>
<Profile />
</TabBarIOS.Item>
</TabBarIOS>
);
If you see in code, in first and third tab, i'm showing content of the item by puting component name in tags like
<Courses />
But for second item, i tried using navigatorios to show component, but it shows only a blank page with title. it doesn't show the content of component. i see lots of examples working like that, but it didn't work for me. maybe because i'm not using navigator or navigaatorios for index.ios , because in most examples i see, they put navigatorios for index and set initialroute. i tried it, but didn't work for me.
Everything works fine till here. In Courses page, I have a list view with items under it (actually items with header, which are collapsible) , when user clicks on each item , I need to redirect user to a page to show that course’s details. (I should pass some arguments also).
render(){
return (
<View style={{
flex: 1
}}>
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow.bind(this)}
style={styles.listView}
/>
</View>
);
}
renderRow(data) {
var header = (
<View>
<View style={styles.rowContainer}>
<View style={styles.textContainer}>
<Text style={styles.title}>{data.nid}</Text>
<Text style={styles.description} numberOfLines={0}>{data.title}</Text>
</View>
</View>
<View style={styles.separator}></View>
</View>
);
///////////
var cid = [];
var content = [];
for(let x=0; x < Object.keys(data.course).length; x++){
cid[x] = data.course[x].course_id;
content.push(
<TouchableHighlight
underlayColor='#e3e0d7'
key={x}
onPress={()=> {
this.rowPress(x); ///// here i need to redirect user to another page to show course's details
}}
style={styles.child}
>
<Text style={styles.child}>
{data.course[x].title}
</Text>
</TouchableHighlight>
);
}
var clist = (
<View style={styles.rowContainer}>
{content}
</View>
);
////////////
return (
<Accordion
header={header}
content={clist}
easing="easeOutCubic"
/>
);
}
I want to redirect user to a page and show details, and i want to have a header title and a back button (like Navigator or NavigatorIOS).
I've found a sample app that is doing exactly what i'm looking for, but it's too complicated for me, that i didn't understand how it is working,
react native tabbar-navigator (iOS)
I've looked into many examples and tutorials. i tried to implement their code into mine but it didn't work.
Also find some other tutorials using redux, but it's so complicated and hard for me. i'm looking for something more simpler.
Navigation using Redux
Looking forward to hearing from you,
Any help is highly appreciated. Thanks in Advance!
I found out that when i have few scenes and i want to navigate between them , best practice is to use Navigator or NavigatorIOS.
I continue my app and did few more scenes and components ( with few levels going deep ) and i found out that Navigator or NavigatorIOS is not working properly for that purpose. Then i switched to NavigationExperimental and that was awesome. Then i had some problems in state management, i found out about redux. it was not easy at first, but when i start it, you will love it.
So for newbies like me, it's better to start with redux at first. that would make life much easier for you :)
Related
i got an problem with the refreshing on pull function. The FlatList renders fine, but pull to refresh is not working. This is my current sourcecode:
return (
<View style={GlobalStyles.flex1}>
<FlatList
showsVerticalScrollIndicator={false}
refreshControl={
<RefreshControl
refreshing={isRefreshing}
onRefresh={() => {
console.log("onRefresh loadVocable");
loadVocables();
}}
/>
}
data={vocables}
keyExtractor={vocable => vocable.id}
onEndReached={() => {
if (!isRefreshing && !endReached) {
loadVocables();
}
}}
renderItem={vocable => (
<TouchableOpacity
onPress={() => {
props.navigation.navigate({ routeName: "editVocable", params: { vocable: vocable.item } });
}}
onLongPress={() => {
handleLongPress(vocable.item.id);
}}>
<Card style={styles.cardStyle}>
<View style={styles.part1}>
<Text style={styles.vocableText}>{vocable.item.wordENG}</Text>
<Text style={styles.vocableText}>{vocable.item.wordDE}</Text>
</View>
<View style={styles.part2}>
<Ionicons name={vocable.item.known ? "md-checkmark-circle" : "md-close-circle"} size={23} color={vocable.item.known ? Colors.success : Colors.danger} />
</View>
</Card>
</TouchableOpacity>
)}
/>
</View>
);
In the official docs is an example that says contentContainerStyle needs to be flex: 1 to know the height, that makes sence to me, so when i set contentContainerStyle with flex 1, refresh on pull works fine, but then i can't scroll anymore in the Flatlist and everthing get very tight, so the style also change then. Does anyone know why this happen?
The first picture is with "contentContainerStyle={{flex: 1}}" and the last one is without contentContainerStyle.
The answer was so easy, I compared a new project (there worked my code) to the one where the problem was and after 5 days I found the little error:
My import was wrong!
I imported FlatList like this:
import { FlatList } from "react-native-gesture-handler";
But it needs to get imported from React-Native so like this:
import { FlatList } from "react-native";
Thanks to #The1993, without the hint to compare the projects, maybe I would stuck forever on this error :D In the future I will compare working files to find any error!
contentContainerStyle is used to style inner content e.g items alignments, padding, etc
style is used to align its height and relations
You can replace style={{flex: 1}} instead of contentContainerStyle or wrap the parent element with flex: 1
So let's say I have a stateless component. I want this component to
display a static title but also map through an array that's
being passed in. I only want to do it this way due to styling
issues. Is this possible or is there another way to go about this?
Thanks!
const ListTitle = ({ style, title, icon, checkedItems, onPressExpand }) => (
<View>
<TouchableOpacity onPress={onPressExpand}>
<View style={ [style, baseStyles.touchableList] }>
<Text>{title}</Text>
{icon}
</View>
</TouchableOpacity>
{
checkedItems.map((item, i) => (
<View>
<Text>{item}</Text>
</View>
))
}
</View>
)
checkedItems is the array I want to pass in. {checkedItems}.map doesn't look right but neither does the way I tried. I'm starting to think this isn't possible but wanted to know what others have to say.
So Basically I am getting error in the title which is related to the navigator.
The error pops up when I press on the Icon.
What I basically want to do is make a Tab bar at the top that switches between three different views: feed, wiki, and message board
Here is my index.android.js: (imports Nav)
_renderScene(route, navigator) {
var globalNavigatorProps = {navigator};
switch(route.ident) {
case "FeedView":
return(
<Feed
{...globalNavigatorProps}
/>
);
case "WikiView":
return(
<View>
<Text>
{'Hello'};
</Text>
</View>
);
case "BoardView":
return(
<View>
<Text>
{'Hello'};
</Text>
</View>
);
default:
console.log(`Something went wrong ${route}`);
}
}
render(){
return(
<View>
<Nav />
<Navigator
initialRoute={{ident:"Feed"}}
ref="appNavigator"
renderScene={ this._renderScene }
/>
</View>
);
}
Here is my Nav.js:
constructor(props){
super(props);
}
render(){
console.log(this.props.navigator);
return(
<View style={{flexDirection: "column"}}>
<View style={styles.nav}>
<Icon onPress={(event) => this.props.navigator.push({ident: "Feed"})} name="newspaper-o" size={22}/>
<Icon name="wikipedia-w" size={22}/>
<Icon name="comments" size={22}/>
</View>
<View style={styles.divider}/>
</View>
);
}
_changeView(type){
}
I dont think this is the issue, but the renderScene function won't be bound to the react component.
Try turning renderScene={ this._renderScene } into renderScene={ this._renderScene.bind(this) }
If you are trying to implement a tabbed view there are better ways of doing it you can always use an open source module such as this one https://github.com/skv-headless/react-native-scrollable-tab-view
the developer has made it in such a way that it is easy to use and the example is good enough to get through most of the part.
So instead of creating such components yourself what I would suggest is to use the modules made by the community.
Hope my answer was helpful.
this error always occurs when you didnt bind(this),check you Icon module onPress method
The code I am writing is for wordpress.
I have succeed in fetching titles, category IDs and featured media IDs. Then I try to fetch the image uri to display it.
The wired thing is: Every time the post title and category id and author id come very fast, however, the image doesn't show until I press load more (which is built in by Gifted Listview). The requests happen both at "load more" and "ListViewOnFresh", so it should be like this.
I tried to use console.log to output "start loading" and "loading finished" when image starts and ends ending. However, I can see it was never loaded unless I press load more.
Even if it is loaded, if I pull to refresh (call the ListViewOnRefresh), it will disappear again.
I tried also to output dataRows, it has no problem at all, the featured_image is showing the right uri.
I really cannot solve this. Thank you in advance for your help.
var MovieListScreen = React.createClass({
componentDidMount: function() {
Controllers.NavigationControllerIOS("movies_nav").setLeftButtons([{
title: "Categories",
onPress: function() {
Controllers.DrawerControllerIOS("drawer").toggle({side:"left"});
}
}]);
},
renderListViewRow: function(row){
return(
<View >
<TouchableHighlight underlayColor={'#f3f3f2'} onPress={()=>this.selectRow(row)}>
<View style={styles.articleContainer}>
<View style={styles.rowDetailsContainer}>
<Image resizeMode="cover" style={styles.featuredImage}
source={{uri: row.featured_image}}
onLoadStart={() =>{console.log('start loading')}}
onLoadEnd={() => {console.log('loading finished')}}
/>
<Text style={styles.articleTitle}>
{row.title.rendered}
</Text>
<Text style={styles.articleTime} >
Posted by {row.author}, Category: {row.categories[0]}
</Text>
<Text style={styles.articleExcerpt}>
{row.excerpt.rendered}
</Text>
</View>
</View>
</TouchableHighlight>
<View style={styles.separator}/>
<View style={styles.articleActions}>
<Icon style={{flex:1}} name="share-alt" size={20} color="#0088CC" />
<Icon style={{flex:1}} name="thumbs-o-up" size={20} color="#0088CC" />
<Icon style={{flex:1}} name="star-o" size={20} color="#0088CC" />
<View style={{flexDirection:'row',justifyContent:'center',alignItems:'center'}}><Icon style={{flex:1}} name="external-link" size={20} color="#0088CC" /><Text style={{fontSize:15,color:'#0088CC'}}> Read More</Text></View>
</View>
</View>
);
},
listViewOnRefresh: function(page, callback){
var rowsData = [];
var REQUEST_URL = 'http://jo.wtf/wp-json/wp/v2/posts?per_page=10&order=asc&page='+page;
fetch(REQUEST_URL)
.then((response) => response.json())
.then((responseData) => {responseData.map((obj)=>{
fetch('http://jo.wtf/wp-json/wp/v2/media/'+obj.featured_media)
.then((responseMedia) => responseMedia.json())
.then((responseDataMedia) => {
obj.featured_image= responseDataMedia.guid.rendered;
})
rowsData.push(obj);
console.log(rowsData);
})
callback(rowsData);
return;
})
.done();
},
selectRow: function(row){
var navigationController = Controllers.NavigationControllerIOS("movies_nav");
navigationController.push({
component: "PushedScreen", // the unique ID registered with AppRegistry.registerComponent (required)
backButtonTitle: "", // override the nav bar back button title for the pushed screen (optional)
backButtonHidden: false, // hide the nav bar back button for the pushed screen altogether (optional)
});
},
render: function() {
return (
<RefreshableListView renderRow={(row)=>this.renderListViewRow(row)}
onRefresh={(page, callback)=>this.listViewOnRefresh(page, callback)}
backgroundColor={'#EFEFEF'}
style={styles.listview}/>
);
},
});
i think you should add
style={{width:200,height:300}}
to your Image tag
I have solved this problem in another way.
I tried to rewrite the code with async functions but it didn't help either. I think it is caused by 2 api calls at the same time, although why I cannot do that.
Anyway, I don't want to call one API to fetch the thumbnail ID and then call N APIs to get the url for those thumbnails, so I changed the wordpress API.
Add some code to the function.php file into my theme solved it.
It seems I cannot insert php code here... See here:
http://jo.wtf/adding-extra-fields-to-wp-api-output/
I am a react-native newbie. I am wondering if there is a "correct" way to develop a react-native app? As the documentation is still very insufficient, I am afraid I may develop it in the very incorrect manner, and I prefer correct the mistake now, rather than after the project expands. From what I understand from my previous experience, we should not combine all pages in a single .js file, but how can each component communicate with each other?
I am currently doing like this inside index.android.js:
import Login from './Login';
import Register from './Register';
import Home from './Home';
class TheProject extends Component {
renderScene (route, navigator) {
_navigator = navigator;
switch (route.index) {
case 'Login':
return (
<View style={styles.container}>
<Login navigator={navigator} />
</View>
);
case 'Register':
return (
<View style={styles.container}>
<Register navigator={navigator} />
</View>
);
}
}
render() {
return (
<Navigator
initialRoute={{index: 'Login'}}
renderScene={this.renderScene}
/>
);
}
}
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'space-around',
backgroundColor: '#F0F0F0',
flexWrap:'wrap'
},
});
AppRegistry.registerComponent('TheProject', function() { return TheProject });
module.exports = TheProject;
and in my Login.js (other.js file will be similar):
export default class Login extends React.Component {
constructor(props) {
super(props);
this.state = {
username: '',
password: '',
};
}
registerOnPress() {
this.props.navigator.push({
index: 'Register'
});
}
loginOnPress() {
if (this.state.username != '' && this.state.password != '') {
Alert.alert('Success!', 'Successfully logged in.');
this.props.navigator.push({
index: 'Home'
});
} else {
Alert.alert('Failed to log-in', 'Wrong username or password');
}
}
render () {
return (
<View style={styles.individualContainer}>
<View style={styles.content}>
<View style={styles.formField}>
<View style={styles.input}>
<Text style={styles.label}>Username : </Text>
<View style={styles.fieldBox}>
<TextInput
style={styles.field}
underlineColorAndroid={'transparent'}
onChangeText={(data) => this.setState({ username: data })}
/>
</View>
</View>
<View style={styles.input}>
<Text style={styles.label}>Password : </Text>
<View style={styles.fieldBox}>
<TextInput
style={styles.field}
underlineColorAndroid={'transparent'}
secureTextEntry={true}
onChangeText={(data) => this.setState({ password: data })}
/>
</View>
</View>
</View>
<View style={styles.input}>
<TouchableHighlight style={styles.buttonBox} onPress={this.loginOnPress.bind(this)}>
<Text style={styles.buttonText}>Login</Text>
</TouchableHighlight>
</View>
<View style={styles.input}>
<TouchableHighlight style={styles.buttonBox} onPress={this.registerOnPress.bind(this)}>
<Text style={styles.buttonText}>Register</Text>
</TouchableHighlight>
</View>
</View>
</View>
);
}
}
I know there are a lot of ways to develop, but am I on the right track? I am quite blurred when it comes to component mount and unmount.
Your question is very vague, phrased in such a way that the only real answer is "there is no single right answer".
I suggest looking at the Awesome React Native - Seeds list for good starter kits and the Examples list as well.
Communication between components is quite straight-forwarded and is covered by Facebook's documentation on the subject.
You should definitely not develop your entire application in a single file.
Keep in mind that you do not need "React native documentation" to write react native at the beginning. First you should understand the fundamentals of React because once you do, you'll notice that those fundamentals apply identically whether you're writing a web or native app, the only thing that differs are the components used.
At first I was about to vote for closing this question, but it's somehow fascinating and tech-related if we just look through the right glasses :)
At first, you should note you have a lot of nested <View> components. This could be re-structured, where both username and password label + textinput would be applied as a component - receiving text label and onChangeText as props.
Same goes with Login and Register buttons, create them as separate component, where you define title of the button and loginOnPress/registerOnPress functions as props.
Remember to use propTypes whenever needed. This helps you and other devs to keep on track what happens in different components and how they're related to each other. For instance: Login.propTypes = { navigator: PropType.func.isRequired}
Use Flow (http://flowtype.org) with you project for types and annotations.