Component spinner not working - react-native

i create a component call Spinner so:
//spinner.js
import React, { Component } from 'react';
import {
Image,
StyleSheet,
View,
Text,
KeyboardAvoidingView,
TouchableHighlight,
Modal,
Button,
ActivityIndicator,
} from 'react-native';
export default class Spinner extends Component{
constructor(props){
super(props);
this.state={
visible:this.props.visible
};
this._show=this._show.bind(this);
this._hide=this._hide.bind(this);
}
render(){
return(
<Modal
animationType={'none'}
transparent={true}
visible={this.state.visible}
onRequestClose={this.props.onDismissLoadingCallback}>
<View style={{flex:1}}/>
<View style={{
height:80,
width:80,
alignItems:'center',
justifyContent:'center',
backgroundColor:'#3434347f',
borderRadius:10,alignSelf:'center'}}>
<ActivityIndicator
animating={true}
size={"large"}
color={'white'}
/>
</View>
<View style={{flex:1}}/>
</Modal>
);
}
_show() {
this.setState({visible:true});
}
_hide(){
this.setState({visible:false});
}
}
in this create methods _show() and _hide()
but no working when is called from other class, i call from class Login.js
class Login extends Component {
constructor(props) {
super(props)
this.state = { visible: false };
}
_onLoginPress() {
this.Spinner._show()
)
}
_redirect() {
this.Spinner._hide()
}
render() {
return (
<Spinner visible= {this.state.visible}/>
<TouchableHighlight style={styles.button}
onPress={this._onLoginPress}
activeOpacity={1} >
<Text style={styles.textButtonLogin}>Visible</Text>
</TouchableHighlight>
<TouchableHighlight style={styles.button}
onPress={this._redirect}
activeOpacity={1} >
<Text style={styles.textButtonLogin}>Not Visible</Text>
</TouchableHighlight>
)
}
when set true in the constructor it if show, but when set false in the constructor it not show, it could show when press button _onLoginPress, and not show when is pressed button _redirect().

For using <Spinner /> reference correctly, you have to
<Spinner ref={(ref) => this.Spinner = ref} visible= {this.state.visible} />
And then your this.Spinner._show(), this.Spinner._hide() should work.

Related

How to create a separate class for a component in react native and use it as a common class?

Hi I am learning react native. I am using Modal component of react native. I need to use the same across multiple times in app. Here the code
Now I am trying to call the function
{this.createModal(dataForMaritalStatus)}
instead of
/* <Modal visible={this.state.isModalVisible}
onRequestClose={() => {
this.setState({ isModalVisible: false })
}}
animationType="fade"
transparent={true}
>
<View style={styles.modalContainer}>
<ScrollView
showsVerticalScrollIndicator={true}
>
{dataForMaritalStatus === null ? <Text style={styles.nodata}>No data Found </Text> : dataForMaritalStatus.map((status, id) => (
<View key={id}>
<TouchableOpacity
style={styles.opacity}
onPress={() => {
this._toggleModal()
}}>
<Text style={styles.taskList}>{status.value}</Text>
</TouchableOpacity>
</View>
))}
</ScrollView>
</View>
</Modal>
*/
So how to make a common class for this component and pass different arrays of data and use it in render method ? The data is going to be different for different purposes and I need to maintain different states for different purposes.
Edit : I have written a method for it,but it calls the function but it does not render the modal, do I need to render it ?
createModal = (data) => {
<Modal visible={this.state.isModalVisible}
onRequestClose={() => {
this.setState({ isModalVisible: false })
}}
animationType="fade"
transparent={true}
>
<View style={styles.modalContainer}>
<ScrollView
showsVerticalScrollIndicator={true}
>
{data === null ? <Text style={styles.nodata}>No data Found </Text> : data.map((status, id) => (
<View key={id}>
<TouchableOpacity
style={styles.opacity}
onPress={() => {
this._toggleModal()
}}>
<Text style={styles.taskList}>{status.value}</Text>
</TouchableOpacity>
</View>
))}
</ScrollView>
</View>
</Modal>
}
Solution 1
Create a separate file customModalComponent.js, and pass in the array data through props. Change your Modal component a little bit, use this.props.dataForMaritalStatus for dataForMaritalStatus..
<ScrollView showsVerticalScrollIndicator={true}>
{this.props.dataForMaritalStatus === null ? <Text style={styles.nodata}>No data Found </Text>
: this.props.dataForMaritalStatus.map((status, id) => (
...
)}
</ScrollView>
and then on any other file, import CustomModal from './customModalComponent' and use it this way,
<CustomModal dataForMaritalStatus={yourArrayOfData}/>
Solution 2
If you are just using it in the same file, create a function instead
class myClass extends Component {
constructor(props) {
super(props);
this.createModal = this.createModal.bind(this);
}
render() {
...
}
createModal(dataForMaritalStatus) {
return (
//Insert your Modal code here
...
)
}
}
and use it this way in your render,
render() {
<View>
...
{
this.createModal(yourArrayOfData)
}
...
</View>
}
create new component in one folder.
app -> CommonModal.js
CommonModal.js
import React, { Component } from 'react';
import { View, Text, Modal, TouchableOpacity } from 'react-native';
export default class CommonModal extends Component{
constructor(props) {
super(props);
}
}
render(){
return(
<Modal visible={this.state.isModalVisible}
onRequestClose={() => {
this.setState({ isModalVisible: false })
}}
animationType="fade"
transparent={true}
>
<View style={styles.modalContainer}>
<ScrollView
showsVerticalScrollIndicator={true}
>
{this.props.dataForMaritalStatus === null ? <Text style={styles.nodata}>No data Found </Text> : this.props.dataForMaritalStatus.map((status, id) => (
<View key={id}>
<TouchableOpacity
style={styles.opacity}
onPress={() => {
this._toggleModal()
}}>
<Text style={styles.taskList}>{status.value}</Text>
</TouchableOpacity>
</View>
))}
</ScrollView>
</View>
</Modal>
)
}
note: i have used this.props.dataForMaritalStatus
And then use it wherever you need the component
app -> Second.js
Second.js
import React, { Component } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import CommonModal from './CommonModal';
export default class Second extends Component{
constructor(props){
super(props);
this.state={
dataForMaritalStatus:['val1','val2']
}
}
render(){
return(<View style={{flex:1}}>
<CommonModal dataForMaritalStatus={this.state.dataForMaritalStatus}/>
</View>)}
}
Create a separate component for Model
import React, { Component } from "react";
import { Text, View, Modal, ScrollView, TouchableOpacity, Text } from "react-native";
export default class CustomModel extends Component {
render() {
const { dataForMaritalStatus } = this.props;
return (
<Modal
visible={this.state.isModalVisible}
onRequestClose={() => {
this.setState({ isModalVisible: false });
}}
animationType="fade"
transparent={true}
>
<View style={styles.modalContainer}>
<ScrollView showsVerticalScrollIndicator={true}>
{dataForMaritalStatus === null ? (
<Text style={styles.nodata}>No data Found </Text>
) : (
dataForMaritalStatus.map((status, id) => (
<View key={id}>
<TouchableOpacity
style={styles.opacity}
onPress={() => {
this._toggleModal();
}}
>
<Text style={styles.taskList}>{status.value}</Text>
</TouchableOpacity>
</View>
))
)}
</ScrollView>
</View>
</Modal>
);
}
}
don't forget to export that component.
Now import that component in the file where you want to use that
import Model from "./CustomModel";
and use it this way
<CustomModel dataForMaritalStatus=[] />
you can pass data using props like a do above.
you can learn more about props here: https://facebook.github.io/react-native/docs/props

React Native: TypeError: undefined is not an object (evaluating 'this.props.navigation.navigate')

Being a beginner in react-native, I can't figure out the problem in my code. By reading on the internet, I have an idea that I have some binding issue maybe.
So, my code starts with index.js and registers the App component over there. The app component just contains the stack navigation routes. It load the LoginScreen component (displays logo, background and name of the application) which in turn loads LoginForm component. There is no authentication on the Login button and the only thing I need is that the Menu component is loaded as I press the Login button. It is giving the TypeError: undefined is not an object (evaluating 'this.props.navigation.navigate')
index.js
import { AppRegistry } from 'react-native';
import App from './App';
AppRegistry.registerComponent('bluebulk', () => App);
App.js
import { StackNavigator } from 'react-navigation';
import LoginScreen from './src/components/login/LoginScreen';
import Menu from './src/components/menu/Menu';
const App = StackNavigator({
Main: { screen: LoginScreen },
Menu: { screen: Menu }
});
export default App;
LoginScreen.js
import { StackNavigator } from 'react-navigation';
import React, { Component } from 'react';
import { StyleSheet, View, Text, Image } from 'react-native';
import LoginForm from './LoginForm';
class LoginScreen extends Component {
render() {
return (
<View style={styles.container}>
<View style={styles.logoContainer}>
<Image
style={styles.logo}
source={require('../../images/transparent.png')}
/>
<View style={{ flexDirection: 'row' }}>
<Text style={styles.blueTextStyle}>Blue</Text>
<Text style={styles.bulkTextStyle}>Bulk</Text>
</View>
</View>
<View style={styles.formContainer}>
<LoginForm />
</View>
</View>
);
}
}
export default LoginScreen;
LoginForm.js
import React, { Component } from 'react';
import {
StyleSheet,
TextInput,
TouchableOpacity,
Text,
View,
KeyboardAvoidingView,
Keyboard
} from 'react-native';
import { StackNavigator } from 'react-navigation';
class LoginForm extends Component {
render() {
return (
<KeyboardAvoidingView behavior='height' style={styles.container}>
<View style={{ flexDirection: 'row' }}>
<Text style={styles.textStyle}>Email:</Text>
<TextInput
style={styles.styleInput}
placeholder="user#gmail.com"
returnKeyType="next"
keyboardType="email-address"
onSubmitEditing={() => this.refs.password.focus()}
/>
</View>
<View style={{ flexDirection: 'row' }}>
<Text style={styles.textStyle}>Password:</Text>
<TextInput
ref='password'
style={styles.styleInput}
placeholder="password"
secureTextEntry
returnKeyType="go"
onSubmitEditing={Keyboard.dismiss}
/>
</View>
<TouchableOpacity
style={styles.buttonContainer}
onPress={() => this.props.navigation.navigate('Menu')} //Error here
>
<Text style={styles.buttonText}>Login</Text>
</TouchableOpacity>
</KeyboardAvoidingView>
);
}
}
export default LoginForm;
Menu.js
import React, { Component } from 'react';
import { StyleSheet, View, Text, TouchableOpacity } from 'react-native';
import { StackNavigator } from 'react-navigation';
class Menu extends Component {
render() {
const { navigate } = this.props.navigation;
return (
<View style={styles.container}>
<View style={styles.viewContainer}>
<TouchableOpacity style={styles.buttonContainer}>
<Text style={styles.buttonText}>View Products</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.buttonContainer}>
<Text style={styles.buttonText}>View Discounts/Offers</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.buttonContainer}>
<Text style={styles.buttonText}>View Invoice History</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
export default Menu;
You need to pass navigation props lower down to your LoginForm component.
Try this: <LoginForm navigation={this.props.navigation} />
You should end up with the following result:

react-native router flux Actions is not navigating to other page

import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Navigator,
TouchableOpacity,
Image,
Button
} from 'react-native';
import Actions from 'react-native-router-flux';
import First from './First';
export default class Home extends Component{
componentWillMount() {
}
render(){
return(
<View>
<View style={{height:220,backgroundColor:'#DCDCDC'}}>
<Image style={{width:120,height:120,top:50,left:120,backgroundColor:'red'}}
source={require('./download.png')} />
</View>
<View style={{top:30}}>
<View style={{flexDirection: 'row', alignItems: 'center'}}>
<TouchableOpacity style= { styles.views}
onPress = {()=>{ Actions.First({customData: 'Hello!'}) }}>
<Text style={{fontSize:20, textAlign:'center',color:'white',top:20}}> Profile </Text>
</TouchableOpacity>
<TouchableOpacity style= { styles.views1} >
<Text style={{fontSize:20, textAlign:'center',color:'white',top:20}}> Health Tracker </Text>
</TouchableOpacity>
</View>
</View>
</View>
);
}
}
In the above code, Actions in not working means not navigating to First.js page, how can i edit my code, and i have not written anything in ComponentWillMount() function, what i should write inside that?ataomega
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Navigator,
TouchableOpacity
} from 'react-native';
import Home from './Home';
export default class Prof extends Component{
constructor(){
super()
}
render(){
return (
<Navigator
initialRoute = {{ name: 'Home', title: 'Home' }}
renderScene = { this.renderScene }
navigationBar = {
<Navigator.NavigationBar
style = { styles.navigationBar }
routeMapper = { NavigationBarRouteMapper } />
}
/>
);
}
renderScene(route, navigator) {
if(route.name == 'Home') {
return (
<Home
navigator = {navigator}
{...route.passProps}
/>
)
}
}
}
var NavigationBarRouteMapper = {
LeftButton(route, navigator, index, navState) {
if(index > 0) {
return (
<View>
<TouchableOpacity
onPress = {() => { if (index > 0) { navigator.pop() } }}>
<Text style={ styles.leftButton }>
Back
</Text>
</TouchableOpacity>
</View>
)
}
else { return null }
},
RightButton(route, navigator, index, navState) {
if (route.openMenu) return (
<TouchableOpacity
onPress = { () => route.openMenu() }>
<Text style = { styles.rightButton }>
{ route.rightText || 'Menu' }
</Text>
</TouchableOpacity>
)
},
Title(route, navigator, index, navState) {
return (
<Text style = { styles.title }>
{route.title}
</Text>
)
}
};
First of all I recommend you to create a rounter component and make your app launch from there:
Something like this
import { Scene, Router, ActionConst } from 'react-native-router-flux';
import First from 'yourRoute';
const RouterComponent = () => {
<Router>
<Scene
key="First"
component={First}
initial />
... your other scenes
</Router>
}
export default RouterComponent;
then in your index page or wherever you load from just add this component
import React, { Component } from 'react'
import RouterComponent from './Router'
class AppContainer extends Component {
render() {
return (
<RouterComponent />
);
}
}
export default AppContainer;
now you can call it from your code. Any doubts ask them :P

React-native pushing to other class

import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Navigator,
TouchableOpacity,
Image
} from 'react-native';
import First from './First';
export default class Home extends Component{
navSecond(){
this.props.navigator.push({
id: 'First',
title: 'First',
name: 'First',
component: First
})
}
render(){
return(
<View>
<View style={{height:220,backgroundColor:'#DCDCDC'}}>
<Image style={{width:120,height:120,top:50,left:120,backgroundColor:'red'}}
source={require('./download.png')} />
</View>
<View style={{top:30}}>
<View style={{flexDirection: 'row', alignItems: 'center'}}>
<TouchableOpacity style= { styles.views} onPress={this.navSecond.bind(this)}>
<Text style={{fontSize:20, textAlign:'center',color:'white',top:20}}> Profile </Text>
</TouchableOpacity>
<TouchableOpacity style= { styles.views1} >
<Text style={{fontSize:20, textAlign:'center',color:'white',top:20}}> Health Tracker </Text>
</TouchableOpacity>
</View>
<View style={{flexDirection: 'row', alignItems: 'center'}}>
<TouchableOpacity style= { styles.views2} >
<Text style={{fontSize:20, textAlign:'center',color:'white',top:20}}> Medical Care </Text>
</TouchableOpacity>
<TouchableOpacity style= { styles.views3} >
<Text style={{fontSize:20, textAlign:'center',color:'white',top:20}}> Alerts </Text>
</TouchableOpacity>
</View>
<View style={{flexDirection: 'row', alignItems: 'center'}}>
<TouchableOpacity style= { styles.views4} >
<Text style={{fontSize:20, textAlign:'center',color:'white',top:20}}> Health Topics </Text>
</TouchableOpacity>
<TouchableOpacity style= { styles.views5} >
<Text style={{fontSize:20, textAlign:'center',color:'white',top:20}}> My Documents </Text>
</TouchableOpacity>
</View>
</View>
</View>
);
}
}
In this code i need to navigate to First.js using push, but i am not able to do that. By clicking on Profile it should navigate to First.js, here push() is working but that is not navigating to First.js. The above page i set as initial route, then how can i link to all pages?
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Navigator,
TouchableOpacity
} from 'react-native';
import Home from './Home';
export default class Prof extends Component{
constructor(){
super()
}
render(){
return (
<Navigator
initialRoute = {{ name: 'Home', title: 'Home' }}
renderScene = { this.renderScene }
navigationBar = {
<Navigator.NavigationBar
style = { styles.navigationBar }
routeMapper = { NavigationBarRouteMapper } />
}
/>
);
}
renderScene(route, navigator) {
if(route.name == 'Home') {
return (
<Home
navigator = {navigator}
{...route.passProps}
/>
)
}
}
}
var NavigationBarRouteMapper = {
LeftButton(route, navigator, index, navState) {
if(index > 0) {
return (
<View>
<TouchableOpacity
onPress = {() => { if (index > 0) { navigator.pop() } }}>
<Text style={ styles.leftButton }>
Back
</Text>
</TouchableOpacity>
</View>
)
}
else { return null }
},
RightButton(route, navigator, index, navState) {
if (route.openMenu) return (
<TouchableOpacity
onPress = { () => route.openMenu() }>
<Text style = { styles.rightButton }>
{ route.rightText || 'Menu' }
</Text>
</TouchableOpacity>
)
},
Title(route, navigator, index, navState) {
return (
<Text style = { styles.title }>
{route.title}
</Text>
)
}
};
As your app grows you'll find out that the Navigator is not enough. So I offer you to use react-native-router-flux. It's works well.
you can simply navigate to any scene and send the data as props.
for example :
import React, { Component } from 'react';
import { ... } from 'react-native';
import Actions from 'react-native-router-flux';
export default class Example extends Component {
componentWillMount() {
}
render() {
return (
<View>
<TouchableOpacity
onPress={()=>{ Actions.media({customData: 'Hello!'}) }}
><Text>Navigate to scene Media</Text></TouchableOpacity>
)
}
}
AppRegistry.registerComponent('Example', () => Example);
Navigating to scene Mediaand passing props named customData with value of 'Hello'

I have ListView Component in a js file and I want to use it another js file and show/hide the component on click of a button dynamically

How should i do it? My code is :
ListComponent.js
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
ListView,
TouchableHighlight
} from 'react-native';
class ListComponent extends Component {
constructor(props) {
super(props);
var dataSource = new ListView.DataSource(
{rowHasChanged: (r1, r2) => r1!== r2});
this.state = {
dataSource: dataSource.cloneWithRows(['A','B','C'])
};
}
renderRow(rowData, sectionID, rowID) {
return (
<TouchableHighlight
<View>
<Text style={styles.instructions}>{rowData}</Text>
</View>
</TouchableHighlight>
);
}
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow.bind(this)}/>
);
}
}
module.exports=ListComponent;
CreateMessage.js
'use strict'
var React= require('react');
var ReactNative = require('react-native');
var {
View,
Text,
Image,
StyleSheet,
TouchableHighlight,
TextInput,
Dimensions,
}= ReactNative;
import { Container, Content, Picker } from 'native-base';
var ListComp=require('./ListComponent');
class CreateMessage extends React.Component{
constructor(props) {
super(props);
this.state = { email: 'Email ID' , pass:'Password', name:'Name', isLoginClicked:'true',language:'ABC',pickerState:false};
}
press(){
this.setState({
pickerState : !this.state.pickerState
});
}
_renderList() {
if (this.state.pickerState) {
return (
<ListComp/>
);
}
else {
return null;
}
}
render(){
return (
<View>
<View>
<View>
<TouchableHighlight
style={{flex:1}}>
<Image
style={styles.headerImage}
source={require('./images/back-arrow.png')}/>
</TouchableHighlight>
<Text> Create Message</Text>
</View>
<View>
<TouchableHighlight>
<Text>Done</Text>
</TouchableHighlight>
</View>
</View>
<View>
<Text>Post to</Text>
<View>
<View>
<Image
style={{height:70,width:70,}}
source={require('./images/no-image.png')}/>
</View>
<View>
<Text
style={styles.text}>name of community</Text>
<Text
style={styles.text1}>no. of members</Text>
</View>
**<TouchableHighlight
underlayColor="gray"
onPress={this.press.bind(this)}>
<Image
style={{height:20,width:20,}}
source={require('./images/add-button.png')}/>
</TouchableHighlight>**
</View>
<Text
style={styles.headingText}>Subject</Text>
<TextInput></TextInput>
<Text
style={styles.headingText}>Message</Text>
<TextInput></TextInput>
<View>
<TouchableHighlight}>
<View>
<Image
style={{height:20,width:20,marginLeft:0,}}
source={require('./images/image-add-button.png')}/>
<Text>Add Photo</Text>
</View>
</TouchableHighlight>
<Text>ADD PROJECT</Text>
</View>
</View>
</View>
);
}
}
module.exports=CreateMessage;
I am displaying CreateMessage.js in my index.ios.js file and it is working fine , but i want to show/hide a list on click of a button (3rd TochableHighlight ).
I assume _renderList is responsible for render your listview component. You can call it in render function.
render(){
return (
<View>
{this._renderList()}
/*......rest of your code....*/
</View>
);