How can I export and import a static in a component in React Native? - static

I'm really new in this ReactJS/React Native thing and found something I just don't understand.
I'm creating static in every screen with the header, which can be different from a screen to another. So for example, my Home looks like this:
static navigationOptions = {
headerTitle: () => <HeaderLogo />,
headerTintColor: "#fff",
headerStyle: {
backgroundColor: "#DA1A31",
elevation: 0,
shadowOpacity: 0,
height: 60
},
headerLeft: (
<TouchableOpacity>
<Image
source={require('../assets/chevronback.png')}
style={{marginHorizontal: 20}}
size={15}
/>
</TouchableOpacity>
),
headerRight: (
<Image
source={require('../assets/menu.png')}
style={{marginHorizontal: 15}}
size={20}
/>
),
};
render() {
return (
///etc
But when I put my home element in App.js, the header is not there:
export default class App extends React.Component {
render() {
return (
<Home/>
)
}
What can I do for the header to show in my home screen? Is there something I am missing?
Thanks

Rather than relying on the react navigation header, i woud suggest to make your own custom header , which would be global component and you can import it in every screen which would act as a header and pass title of screen for the header .
First ive creater a header.js class component :
export default class Header extends Component {
constructor(props){
super(props);
this.state = {
}
}
render(){
return(
<View style={{flexDirection:'row' , paddingBottom :hp("3.125%") , justifyContent:'space-between'}}>
<View style={{opacity:0}}>
<Image source={require('../assets/images/crossIcon.png')} />
</View>
<View >
<Text style={headerStyles.headerText}>{this.props.title}</Text>
</View>
<View style={{left:-20}}>
<TouchableOpacity style={headerStyles.imageView} onPress={() => this.props.navigation.goBack()}>
<Image style={{height:15,width:15}} source={require('../assets/images/crossIcon.png')} />
</TouchableOpacity>
</View>
</View>
)
}
}
then suppose in my Home.js ive imported the header class and passed the title an navigatiobn props to it :
import Header from '../components/Header';
class Home extends React.Component {
constructor(props){
super(props);
}
render(){
return(
<View>
<Header title="Home page" navigation={this.props.navigation}/>
</View>
)
}
}
Hope it helps feel free for doubts.

Related

React native changing img with state Error

First sorry to guys because my eng level is very low.
I'm studying react native.
Try changing image with the state but is not working.
Error : null is not an object (this.state.admob)
index.js
class HomeScreen extends React.Component {
constructor(props){
super(props);
this.state = {admob: require('../Img/admob1.jpg'), admobCount: 0};
}
_changeAdmob(){
this.setState({
if(admobCount = 0){
admobCount: this.state.admobCount + 1;
admob: require('../Img/admob1.jpg');
},
if(admobCount = 1){
admobCount: 0;
admob: require('../Img/admob2.png');
}
});
}
componentDidMount(){
this.admobTimer = setInterval(
() => this._changeAdmob(), 2000
);
}
componentWillUnmount(){
clearInterval(this.admobTimer);
}
render() {
return (
<View style={styles.MasterContainer}>
<NavBar navigation = {this.props.navigation}/>
<UserBar navigation = {this.props.navigation}/>
<View style={{height: 40,}}></View>
<ButtonTab/>
<Admob/>
<TapBar/>
</View>
);
}
}
class Admob extends React.Component{
render() {
return(
<View style={{ flex: 1,alignItems: 'center',justifyContent:'center' }}>
<Image style={{ width: 350, height: 70 }} source={this.state.admob}></Image>
</View>
);
}
}
** I want to image change whenever 2 seconds.**
You need to pass the state on the component <Admob admob={this.state.admob} />
Add this on the index.js
<View style={styles.MasterContainer}>
<NavBar navigation = {this.props.navigation}/>
<UserBar navigation = {this.props.navigation}/>
<View style={{height: 40,}}></View>
<ButtonTab/>
<Admob admob={this.state.admob}/>
<TapBar/>
</View>
Admob.js change this.state to this.props
<Image style={{ width: 350, height: 70 }} source={this.props.admob}></Image>

How to pass Screen Name to another component

I have a common Header component. How can I pass 'Screen Name' to this component?
I want to pass the 'Screen Name' from Home to HeaderStyle.
I want to use the headerstyle in other component and pass 'Screen Name' to the headerstyle
import HeaderStyle From './HeaderStyle '
export default class Home extends Component {
render (){
return (
// <HeaderStyle>Screen Name</HeaderStyle>
<HeaderStyle Name={"Screen Name"}/>
<HeaderStyle />
)
}
export default class HeaderStyle extends Component {
render() {
return (
<View>
<Header >
<View style={{
width: width, height: hp('12%'),
flexDirection: 'row', backgroundColor: '#141414'
}} >
<Left>
<Image style={styles.logo}
source={require('../assets/images/1x/logo.png')}>
</Image>
</Left>
<View style={{ marginLeft: 280, marginTop: 20 }}>
<Text style={{ color: 'white', fontSize: 35, fontWeight: 'bold' }}>
Should be Dynamic Screen Name</Text></View>
<Right>
<TouchableOpacity onPress={this.ShowHideComponent2}>
<Image style={styles.imgsearch} source={require('../assets/test/a.png')}>
</Image>
</TouchableOpacity>
</Right>
</View>
</Header>
{this.showAssests()}
</View>
);
}
}
Create a function and read window.location.pathname , then in Header component render that function, for Example
export default function currentScreenName(){
let screenName = '';
switch(window.location.pathname){
case '/employees':
screenName = 'Employees';
break;
case '/admin':
screenName = 'Admin';
break;
default:
screenName = 'Dashboard';
}
return screenName;
}
//Header.js
<h1>{currentScreenName()}</h1>
You can simply pass the header prop in static navigationOptions directly inside the screen component.
For example
In your screen component
class HomeScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
header: <HeaderStyle Name={"Screen Name"}/>
};
/* render function, etc */
}
Inside HeaderStyle component use the props in the Text
<Text style={{ color: 'white', fontSize: 35, fontWeight: 'bold' }}>
{this.props.Name}
</Text>
Find more information on header customisation here
thanks a lot i solve the problem
in the home Screen i send the screen name like this
<Headerstyle title={"text"} />
and in the HeaderStyle i receive the title like this
<Text >{this.props.title}</Text>

Add data in React Native and Save the State

I'm building a basic React Native application where the user enters his name in a TextInput and on button press his name along with his image is added to a ScrollView in another View. Images are stored and named in accord with the name of the person. Example - Name: 'ABC', the image fetched from assets will be 'ABC.jpg'.
I'm able to do this for one person, but every time I add a new entry the previous one gets overwritten. How can I retain the previous entry yet add another entry?
Home
import React, {Component} from 'react';
import { StyleSheet, Text, View, Image, ScrollView, Button, TouchableWithoutFeedback, TextInput} from 'react-native';
import { createStackNavigator } from 'react-navigation';
class HomeScreen extends React.Component {
render() {
const { navigation } = this.props;
const name0 = navigation.getParam('name0', 'NO-ID');
return (
<View style={styles.container}>
<ScrollView vertical={true} contentContainerStyle={{flexGrow: 1}}>
<Text style={styles.category}>Category 1</Text>
<ScrollView horizontal={true} showsHorizontalScrollIndicator={false}>
<TouchableWithoutFeedback onPress={() => {
this.props.navigation.navigate('Details', {
name: name0,
intro: 'lorem ipsum',
detail1: 'XYZ',
detail2: 'ABC',
});
}}>
<View style={styles.view}>
<Image source={require('./assets/rohit.jpg')} style={styles.image}></Image>
<Text style={styles.text}>{name0}</Text>
</View>
</TouchableWithoutFeedback>
</ScrollView>
</ScrollView>
</View>
)
}
}
Add Data
class AddData extends React.Component {
constructor(props) {
super(props);
this.state = { text: '' };
}
render() {
function onPressLearnMore() {
alert('Hi')
}
return (
<View style={{flex: 1, flexDirection: 'column', justifyContent:'center', alignItems: 'center'}}>
<TextInput
style={{height: 40,width:200}}
onChangeText={(text) => this.setState({input: text})}
/>
<Button
onPress={() => {
this.props.navigation.navigate('Home', {
name0: this.state.input
});
}}
title="Pass Data"
/>
</View>
);
}
}
Navigator
const RootStack = createStackNavigator(
{
Home: HomeScreen,
Details: DetailsScreen,
Data: AddData
},
{
initialRouteName: 'Data',
}
);
export default class App extends React.Component {
render() {
return <RootStack />;
}
}
Screen 1
Screen 2
Because you aren't saving your data from the user input anywhere, simply passing it back to home, it is getting overwritten and as your code sits, it is working! ;)
To simply put a bandaid on what you're doing, because this method of passing data is slightly taboo.. and you cannot achieve what you're asking without some sort of state persistence like AsyncStorage, or... to not have two screens. Because everytime React re-renders your screen any data that was in your state object disappears...
Inside your home component, on did mount you could store user input to state as objects inside an array. IN the below example I am using the user data you are sending back to home, however this would need to be data retrieved from some sort of persistence.
class HomeScreen extends React.Component {
constructor(props) {
super(props)
this.state = {
usersArray: []
}
}
componentDidMount() {
let userInfo = this.props.navigation.getParam('name0', 'NO-ID');
userInfo !== undefined ? this.setState({usersArray:
[...this.state.usersArray, userInfo]}) : console.log('NO USER DATA to add')
}
render() {
const { navigation } = this.props;
const name0 = navigation.getParam('name0', 'NO-ID');
return (
<View style={styles.container}>
<ScrollView vertical={true} contentContainerStyle={{flexGrow: 1}}>
<Text style={styles.category}>Category 1</Text>
<ScrollView horizontal={true} showsHorizontalScrollIndicator={false}>
<TouchableWithoutFeedback onPress={() => {
this.props.navigation.navigate('Details', {
name: name0,
intro: 'lorem ipsum',
detail1: 'XYZ',
detail2: 'ABC',
});
}}>
<View style={styles.view}>
<Image source={require('./assets/rohit.jpg')} style={styles.image}></Image>
{/* <Text style={styles.text}>{name0}</Text> */}
{ this.state.usersArray.map((ele, index) => {
return <Text key={index} style={styles.text}>{ele.name}</Text>
})}
</View>
</TouchableWithoutFeedback>
</ScrollView>
</ScrollView>
</View>
)
}
}
Please keep in mind you may need to change your user data to be objects for this rest and spreading to work.

React native stack navigation goBack() not working

I created common header for all pages, so create header component then i include that header in signup.js component goback navigation function working in signup.js page but not working header component getting undefined object navigate.goback error
Anyone give a solution for that like that i include component
sample code:
import React from 'react';
import { StyleSheet, Text, View, Image, ScrollView, TextInput,KeyboardAvoidingView, StatusBar } from 'react-native';
import {Icon,Body,Button,Title,Left,Right} from 'native-base';
import Expo from "expo";
import { Constants } from 'expo';
import Headerbar from "./../Header/header";
import Statusbar from "./../statusbar";
const googleIcon=require('../../../img/google_icon.png');
const fbIcon=require('../../../img/fb_icon.png');
export default class Socialsignup extends React.Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
return (
<ScrollView style={styles.socialContainer} scrollEnabled={true}>
<Statusbar/>
<Headerbar title="Social Login" />
<View style={styles.socialText}>
<Text style={styles.accountText}>Choose an account</Text>
</View>
<View style={styles.socialIconsBase}>
<View style={styles.socialIconsGoogle}>
<Image source={googleIcon} style={styles.googleIcon}/>
<Text style={styles.iconText}>
Google
</Text>
</View>
<View style={styles.socialIconsGoogle}>
<Image source={fbIcon} style={styles.fbIcon}/>
<Text style={styles.iconText}>
Facebook
</Text>
</View>
</View>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
socialContainer: {
backgroundColor: '#fff',
},
accountText: {
marginTop:25,
fontSize:20,
padding:20
},
socialIconsBase:
{
flexDirection:'row',
flex:1,
marginTop:40,
borderBottomWidth:1,
borderBottomColor:'#a8c0ce'
},
socialIconsGoogle:
{
flex:1,
alignItems:'center',
paddingTop:25,
paddingBottom:25,
borderRightWidth:1,
borderRightColor:'#a8c0ce',
marginBottom:8,
},
fbIcon:{
height:50,
width:50,
},
googleIcon:{
height:50,
width:50,
},
iconText:{
fontSize:15,
marginTop:15
}
});
you need to use this inside the header component :
import { withRouter } from 'react-router'
and then instead of export default HeaderClassName
use export default withRouter(HeaderClassName)
and you can go back by this.props.history.goBack()
You need to use this too:
<BrowserRouter>
<App />
and then add the pages like that
<Route path='/page' component={Page} />

Passing input text back to parent from component

I am using an auto expanding text input field (Link) and I am creating it as a component. My question is when the text is changed how do I pass the value of the data back to the parent? I want to be able to submit the input via the parent so I was thinking of storing the input value in the parents state.
Parent
Calling the child component by using <InputExpand />
render() {
const { navigate } = this.props.navigation;
console.log("Rendering");
return (
<KeyboardAvoidingView behavior="padding" style={{flex: 1}}>
<View style={{flex: 1}}>
<StatusBar hidden={true} />
<View style={styles.headerBar}>
<NavBar navigation={this.props.navigation} goBack={this.goBack} title="MESSAGE DETAILS" backButton={true} showNewMessage={true} />
</View>
<View style={styles.contentWrapper}>
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow}
enableEmptySections={true}
style={styles.listWrapper}
/>
</View>
<View style={styles.footerBar}>
<View style={styles.footerBtnContainer}></View>
<View style={styles.footerInputContainer}>
<InputExpand />
</View>
<View style={styles.footerBtnContainer}>
<Image source={require('../../images/icons/IconSend.png')} style={{width: 20, height: 20}}/>
</View>
</View>
</View>
</KeyboardAvoidingView>
);
}
Component - (Child)
import React, { Component } from 'react'
const {
TextInput,
StyleSheet,
} = require('react-native');
export default class AutoExpandingTextInput extends React.Component {
state: any;
constructor(props) {
super(props);
this.state = {text: '', height: 0};
}
render() {
return (
<TextInput
{...this.props}
multiline={true}
onChange={(event) => {
this.setState({
text: event.nativeEvent.text,
height: event.nativeEvent.contentSize.height,
});
}}
style={[styles.default, {height: Math.max(35, this.state.height)}]}
value={this.state.text}
placeholder={"Type a message..."}
placeholderTextColor={"#fff"}
/>
);
}
}
var styles = StyleSheet.create({
default: {
color: "#fff",
fontSize: 10,
fontFamily: "Avenir-Light",
},
});
Yes, that is exactly what you should do. You create a handler in the parent state and pass it into the child component as a prop.
// parent component
// assuming a property inputText exists in the state
// and use arrow function to preserve the context of `this` to be of the parent class.
onChangeTextHandler = (e) => {
this.setState({
// get the value from TextInput onChangeText event
inputText: e.value,
})
}
render() {
const { navigate } = this.props.navigation;
console.log("Rendering");
return (
<KeyboardAvoidingView behavior="padding" style={{flex: 1}}>
<View style={{flex: 1}}>
<StatusBar hidden={true} />
<View style={styles.headerBar}>
<NavBar navigation={this.props.navigation} goBack={this.goBack} title="MESSAGE DETAILS" backButton={true} showNewMessage={true} />
</View>
<View style={styles.contentWrapper}>
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow}
enableEmptySections={true}
style={styles.listWrapper}
/>
</View>
<View style={styles.footerBar}>
<View style={styles.footerBtnContainer}></View>
<View style={styles.footerInputContainer}>
<InputExpand onChangeTextHandler= {this.onChangeTextHandler}/>
</View>
<View style={styles.footerBtnContainer}>
<Image source={require('../../images/icons/IconSend.png')} style={{width: 20, height: 20}}/>
</View>
</View>
</View>
</KeyboardAvoidingView>
);
}
// Child Component
import React, { Component } from 'react'
const {
TextInput,
StyleSheet,
} = require('react-native');
export default class AutoExpandingTextInput extends React.Component {
state: any;
constructor(props) {
super(props);
this.state = {text: '', height: 0};
}
render() {
const { onChangeTextHandler } = this.props;
return (
<TextInput
{...this.props}
multiline={true}
onChange={(event) => {
// set the state of parent component here...
onChangeTextHandler(event.nativeEvent.text);
this.setState({
text: event.nativeEvent.text,
height: event.nativeEvent.contentSize.height,
});
}}
style={[styles.default, {height: Math.max(35, this.state.height)}]}
value={this.state.text}
placeholder={"Type a message..."}
placeholderTextColor={"#fff"}
/>
);
}
}
var styles = StyleSheet.create({
default: {
color: "#fff",
fontSize: 10,
fontFamily: "Avenir-Light",
},
});
reactjs react-native
You should pass via props a callback for handle input text changes to the component, and use the onChange event of the input text to call that handle from the child component. If the input text doesn't have onChange (or something like that) you could use a onKeyUp. But the general idea is that you send a callback via props from the parent to the child, and you call it from the child to send data to the parent.

Resources