I need inside the file artistPage.js to refer to the TabNavigator in index.ios.js. In particular, I need to change the styles to hide the TabBar when the user is on the page artistPage.
How can I do that? Any ideas?
I tried to transfer styles in the props but there is the read-only mode(
index.ios.js
'use strict'
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
View,
Image,
Text,
NavigatorIOS,
TouchableHighlight,
NavigationBar,
} from 'react-native';
import config from './config';
import ImagesList from './app/imagesList';
import TabNavigator from 'react-native-tab-navigator';
import Badge from './node_modules/react-native-tab-navigator/Badge'
class MyApp extends Component {
constructor(props) {
super(props);
this.state = {
selectedTab: 'images',
showTabBar: true
};
}
render() {
let tabBarStyle = {};
let sceneStyle = {};
if (this.state.showTabBar) {
tabBarStyle = styles.tabBar;
sceneStyle.paddingBottom = 54;
} else {
tabBarStyle.height = 0;
tabBarStyle.overflow = 'hidden';
sceneStyle.paddingBottom = 0;
}
return (
<View style={styles.container}>
<TabNavigator
tabBarStyle={ tabBarStyle }
sceneStyle={sceneStyle}
>
<TabNavigator.Item
titleStyle={styles.title}
selectedTitleStyle={styles.title_select}
selected={this.state.selectedTab === 'images'}
title="TATTOOS"
renderIcon={() => <Image source={require('./images/tabbar/tattoos_icon.png')} />}
renderSelectedIcon={() => <Image source={require('./images/tabbar/tattoos_icon_selected.png')} />}
onPress={() => this.setState({ selectedTab: 'images' })}>
<NavigatorIOS
style={styles.container}
initialRoute={{
title: 'MyApp',
component: ImagesList,
passProps: { showTabBar: true},
}}
navigationBarHidden={true}/>
</TabNavigator.Item>
</TabNavigator>
</View>
);
}
}
AppRegistry.registerComponent('MyApp', () => MyApp);
imageList.js
'use strict'
import React, { Component } from 'react';
import {
StyleSheet,
ListView,
View,
Text,
Image,
Dimensions,
ActivityIndicator,
TouchableHighlight,
RefreshControl
} from 'react-native';
import ArtistPage from './imageCard';
class ImagesList extends Component {
constructor(props) {
super(props);
this.state = {
};
}
_artistPage() {
this.props.navigator.push({
component: ArtistPage
});
}
render() {
return (
<View style={styles.container}>
<TouchableHighlight
onPress={this._artistPage()}
>
<Text>Got to Next Page</Text>
</TouchableHighlight>
</View>
);
}
}
}
module.exports = ImagesList;
artistPage.js
'use strict'
import React, { Component } from 'react';
import {
StyleSheet,
Text,
ListView,
View,
TouchableHighlight,
Image,
} from 'react-native';
class ArtistPage extends Component {
constructor(props) {
super(props);
this.state = {
};
}
_backTo() {
this.props.navigator.pop();
}
render() {
return (
<View>
<TouchableHighlight style={{marginTop: 100, marginLeft: 50}} onPress={() => this._backTo()} >
<Text>Back {this.props.showTabBar.toString()}</Text>
</TouchableHighlight>
</View>
);
}
}
module.exports = ArtistPage;
Here is how to hide TabNavigator: https://github.com/exponentjs/react-native-tab-navigator
let tabBarHeight = 0;
<TabNavigator
tabBarStyle={{ height: tabBarHeight, overflow: 'hidden' }}
sceneStyle={{ paddingBottom: tabBarHeight }}
/>
But I don't understand how to access it from artistPage.js
Thank you!
Data flow in React is one way. What it means in practice is that, to change something that a certain component receives via props, it will need to call back into the parent component, via a function from props.
The React website has a nice intro to the concept.
In your particular case, you could have a tabBarVisible state in MyApp, and inside render, compute the style to apply to the tab bar.
MyApp also can have a method to change this state:
hideTabBar() {
this.setState({ tabBarVisible: true });
}
Now, in order to let ArtistPage toggle that, you can pass the hideTabBar function from MyApp to ArtistPage as a prop, and call it in ArtistPage in a lifecycle hook, like componentDidMount.
Related
I have recently started out with React native and stuck with this.
I wanted to make a login system so I used conditional rendering to render Login Screen and App's Main screen separately based on LoggedInStatus State.
root component:
import React, {Component} from 'react';
import { StyleSheet, Platform, Image, Text, View, ActivityIndicator, AsyncStorage } from 'react-native';
import firebase from 'react-native-firebase'; import SQLite from 'react-native-sqlite-storage'; import Login from './src/screens/Login'; import Home from './src/screens/Home'; import SplashScreen from 'react-native-smart-splash-screen' var db = SQLite.openDatabase({name: 'test.db', createFromLocation:'~sqlite.db'})
export default class App extends Component { constructor(props) {
super(props);
this.state = {
loggedInStatus: false}; };
componentWillMount(){
//SplashScreen.close(SplashScreen.animationType.scale, 850, 500)
SplashScreen.close({
animationType: SplashScreen.animationType.fade,
duration: 450,
delay: 500,
})
db.transaction((tx) => {
tx.executeSql('SELECT * FROM users', [], (tx, results) => {
console.log("Query completed");
var len = results.rows.length;
console.log(len);
if (len > 0) {
console.log("User is Logged in");
this.setState({ loggedInStatus: true });
}
else{
console.log("User is Logged out");
this.setState({ loggedInStatus: false });
}
});
}); };
render() {
if (this.state.loggedInStatus === true) {
return <Home logoutProp={{ LoggedOut: () => this.setState({ loggedInStatus: false }) }}/>
}
else if (this.state.loggedInStatus === false){
return <Login screenProps={{ isLoggedIn: () => this.setState({ loggedInStatus: true }) }}/>
}
return (
<View>
<Text>This is SpashScreen</Text>
</View>
); } }
Now, If user is logged in then Home component is rendered, Home component is a Drawer navigator with Main screen and Drawer screen:
Home Component:
import React from 'react';
import {
DrawerNavigator,
StackNavigator,
TabNavigator
} from 'react-navigation';
import Icon from 'react-native-vector-icons/Ionicons';
import Main from '../src/tabs/Main';
// import Settings from './src/tabs/Settings';
// import Profile from './src/screens/Profile';
import Modal from '../src/screens/Modal';
import Drawer from '../src/components/Drawer';
export default DrawerNavigator({
Home: {
screen: Main,
}
},{
contentComponent: props => <Drawer {...props} />
});
My Drawer Component has a logout button, I need to call logoutProp of the root component onclick of logout button of the Drawer component, how can I achieve this?
Drawer Component:
import React, { Component } from 'react';
import {
Button,
StyleSheet,
Text,
View
} from 'react-native';
import SQLite from 'react-native-sqlite-storage';
var db = SQLite.openDatabase({name: 'test.db', createFromLocation:'~sqlite.db'})
export default class Drawer extends Component {
constructor(props) {
super(props);
}
render() {
return (
<View style={styles.container}>
<View style={styles.header}>
</View>
<View style={styles.body}>
<Button
title="Log Out"
onPress={this.logout}
/>
</View>
</View>
);
}
logout(){
//Need some method to call logoutProp of root component
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5F5F5',
},
header: {
flex:1,
backgroundColor: '#1d337d'
},
body: {
flex:3,
}
});
Any help will be appreciated, Thanks :)
I am trying to print text content of login.php into the screen via "var result", but the fetch function won't alter value of "var result". How can I set value of result from output of the fetch function?
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
StatusBar,
} from 'react-native';
import Logo from '../components/Logo';
import Form from '../components/Form';
import loginapi from '../apis/loginapi';
var result='noresult';
export default class Login extends Component<{}> {
render() {
login();
return (
<View style={styles.container}>
<Logo/>
<Form/>
<Text>
{result}
</Text>
<Text>
</Text></View>
);
}
}
function login() {
result = fetch('https://www.skateandstrike.com/loginsv/login.php').then((text) => {return text;});
}
const styles = StyleSheet.create({
container : {
backgroundColor:'#f05545',
flex: 1,
alignItems:'center',
justifyContent:'center',
}
});
function myFunction() {
this.setState({ showLoading: false });
}
This is not working too, using setState:
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
StatusBar,
} from 'react-native';
import Logo from '../components/Logo';
import Form from '../components/Form';
import loginapi from '../apis/loginapi';
export default class Login extends Component<{}> {
constructor(){
super();
this.state = {
data:'NoData',
}
}
render() {
login();
return (
<View style={styles.container}>
<Logo/>
<Form/>
<Text>
{this.state.data}
</Text>
</View>
);
}
}
function login() {
fetch('https://www.skateandstrike.com/loginsv/login.php').then(data => this.setState(data));
}
const styles = StyleSheet.create({
container : {
backgroundColor:'#f05545',
flex: 1,
alignItems:'center',
justifyContent:'center',
}
});
function myFunction() {
this.setState({ showLoading: false });
}
Am I using setState in a wrong way? Thanks in advance for your help.
When using the fetch API, I'd recommend using a promise, and you parse it if you are setting the state.
React re-renders on state/props change.
sample code:
fetch(url)
.then(data => data.json()) // if needed
.then(data => this.setState(data))
remember to set state in the constructor.
I'm trying to figure out why Match and History aren't showing up whenever I slide my <Drawer/>. The list[] array is what holds those two.
I'm following a tutorial. I'm guessing <List dataArray={list} renderRow={(item) is the problem in SideMenu.js file.
Here's SideMenu.js file:
import React, {Component} from 'react';
import { Text, View} from 'react-native';
import {List, ListItem, Header} from 'react-native-elements';
import Container from "native-base/src/theme/components/Container";
export default class SideMenu extends Component {
constructor(props) {
super(props);
}
render() {
let list = [{
title: "Match",
onPress: () => {
this.props.navigator.replace("Match")
}
}, { // 2nd menu item below
title: "History",
onPress: () => {
this.props.navigator.replace("History")
}
}];
return(
<Container theme={this.props.theme}>
<Header/>
<View>
<List dataArray={list} renderRow={(item) =>
<ListItem button onPress={item.onPress.bind(this)}>
<Text>{item.title}</Text>
</ListItem>
}/>
</View>
</Container>
);
}
}
Here's AppContainer.js file:
import React, {Component} from 'react';
import {Navigator} from 'react-native-deprecated-custom-components';
import Drawer from "react-native-drawer-menu";
import SideMenu from './components/sideMenu';
export default class AppContainer extends Component {
constructor(props) {
super(props);
this.state = {
toggled: false,
store: {}, // holds data stores
theme: null
}
}
toggleDrawer() {
this.state.toggled ? this._drawer.close() : this._drawer.open();
}
openDrawer() {
this.setState({toggled: true});
}
closeDrawer() {
this.setState({toggled: false});
}
renderScene(route, navigator) { // current route you want to change to, instance of the navigator
switch(route) {
default: {
return null;
}
}
}
// handles how our scenes are brought into view
configureScene(route, routeStack) {
return Navigator.SceneConfigs.PushFromLeft; // pushes new scene from RHS
}
render() {
return(
<Drawer
ref = {(ref) => this._drawer = ref}
type = 'default' // controls how menu appears on screen, pushes content to the side
content = {<SideMenu navigator={this._navigator} theme={this.state.theme}
/>}
onClose={this.closeDrawer.bind(this)}
onOpen={this.openDrawer.bind(this)}
openDrawerOffset={0.9}
>
<Navigator
ref={(ref) => this._navigator = ref}
configureScene={this.configureScene.bind(this)}
renderScene={this.renderScene.bind(this)}
/>
</Drawer>
);
}
}
New react native user here. I'm running into an issue and I am not sure how to proceed. I was able to get react-navigation running properly and then began receiving an error: "The component for route must be a a React Component" but unless I'm missing something, I believe that the component I am referencing is a react component. See my index.android.js below and my Home.js below:
//index.android.js
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
import {
TabNavigator,
StackNavigator
} from 'react-navigation';
import Home from './app/components/Home/Home';
import Search from './app/components/Search/Search';
export default class demoApp extends Component {
render() {
return (
<SimpleNavigation/>
);
}
}
export const SimpleNavigation = StackNavigator({
Home: {
screen: Home,
header: { visible: false },
navigationOptions: {
title: 'Home',
header: null
},
},
Search: {
screen: Search,
navigationOptions: {
title: 'test'
},
},
},{});
//Home.js
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Image,
TextInput,
Button,
TouchableHighlight
} from 'react-native';
class Home extends Component {
constructor(props){
super(props);
this.state = {zipCode: ''}
}
navigate = (zipCode) => {
this.props.navigation.navigate('Search', zipCode);
}
render() {
return (
<View style={styles.container}>
<View style={[styles.boxContainer, styles.boxOne]}>
<Image style={styles.logo} source {require('../../images/Logo.png')} />
<Text style={styles.title}>An application to do things</Text>
<TextInput
style={styles.textInput}
placeholder='Enter a Zip Code'
onChangeText={(zipCode) => this.setState({zipCode})}
>
</TextInput>
</View>
<View style={[styles.boxContainer, styles.boxTwo]}>
<TouchableHighlight onPress={() => this.navigate(this.state.zipCode)}>
<Text style={styles.searchBox}>
Search
</Text>
</TouchableHighlight>
</View>
</View>
);
}
}
Any help/react pointers much appreciated. Thank you!
I think the problem is with home.js since you aren't exporting it. Try this :
export default class Home extends Component { ... }
^^^^^^^^^^^^^^
Add those or just add
export default Home;
at the end of the home.js file
const MyNavigator = createStackNavigator({
RouteNameOne: {
screen: () => <HomeScreen/>
},
RouteNameTwo: {
screen: () => <NewScreen/>
}
}, {
initialRouteName: 'RouteNameOne'
});
It will work.
For anyone else coming here, you could be receiving the "The component for route must be a a React Component" error because you don't have a default export, which was the case for me.
export HomeScreen extends React.Component {
...
vs
export default HomeScreen extends React.Component {
...
Hope this helps someone!
In my case putting this code block inside home.js solved the issue
static navigationOptions = {
navigationOptions: {
title: "scren title",
}
};
Here I need to pass a one variable to HomeContainer.But when I click the GO TO ABOUT button I got above error.I'm new to React Native.So I'm not sure that I'm following correct method to pass data to another view.Hope someone will help me.Thanks in advance.
import React, { Component } from 'react'
import {
AppRegistry,
Navigator,
View
} from 'react-native'
import Router from './src/components/Router'
class navigation extends Component {
render() {
return (
<Navigator
initialRoute={{name: 'Router', component: Router, index: 0}}
renderScene={(route, navigator) => {
return React.createElement(route.component, { ...this.props, ...route.passProps, navigator, route } );
}} />
);
}
}
AppRegistry.registerComponent('navigation', () => navigation)
import React, { Component } from 'react'
import {
AppRegistry,
StyleSheet,
Text,
View,
Navigator,
TouchableHighlight,
TextInput
} from 'react-native'
import AboutContainer from './about/AboutContainer'
import HomeContainer from './home/HomeContainer'
export default class Router extends Component {
constructor(){
super()
}
getInitialState() {
return {}
}
_goToHome() {
this.props.navigator.push({
component: HomeContainer,
passProps: {
username: this.state.username,
}
})
}
updateUsername(username) {
this.setState({ username })
}
render() {
return (
<View style={styles.container}>
<TouchableHighlight
onPress={ () => this._goToHome() }
style={ styles.button }>
<Text>
GO TO ABOUT
</Text>
</TouchableHighlight>
<TextInput
onChangeText={ (username) => this.updateUsername(username) }
placeholder="Your Username"
style={ styles.input }
/>
</View>
)
}
}