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

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

Related

React Native - Is not a function - Is Undefined

I have the following code in React Native
import React from "react";
import {
StyleSheet,
Text,
View,
Button,
TextInput,
Image,
ScrollView
} from "react-native";
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
apiData: [],
};
this.getButton();
}
deleteButton(Id){
fetch("http://192.168.2.22:9090/usuario/" + (Id), {
method: "DELETE"
})
.then(responseData => {
console.log(responseData.rows);
})
.done();
this.dataId = null;
}
render() {
const data = this.state.apiData;
let dataDisplay = data.map(function(jsonData) {
return (
<View style={styles.lista} key={jsonData.id}>
<View style={styles.bordeLista}>
<View style={styles.fila}>
<View style={styles.contenedorfoto}>
<Image
style={styles.foto}
source={require("./img/login.png")}
/>
</View>
<View style={styles.datos}>
<Text>Nombre: {jsonData.nombre}</Text>
<Text>E-mail: {jsonData.email}</Text>
<Text>Telefono: {jsonData.telefono}</Text>
</View>
</View>
<View style={styles.fila}>
<View style={styles.contenedorboton}>
<View style={styles.botoniz}>
<Button title="Modificar" onPress={() => {}} />
</View>
<View style={styles.botonde}>
<Button
title="Eliminar"
onPress={() => this.deleteButton(jsonData.Id)}
color="#ee4c4c"
/>
</View>
</View>
</View>
</View>
</View>
);
});
return (
<Text style={styles.titulo}>Usuarios desde BD MySQL</Text>
<ScrollView>
<View>{dataDisplay}</View>
</ScrollView>
</View>
);
}
}
And I want to call deleteButton() from this button
<Button
title="Eliminar"
onPress={() => this.deleteButton(jsonData.Id)}
color="#ee4c4c"
/>
But I get the following error, That the method is not a function and that it is not defined.
Error
How could I use the function? And I'm setting the parameter well (id). Thank you.
PS: I have deleted parts of the code and only left the most important, if you need the full code I can provide it
You're losing the reference to this because you're using an old-style lambda.
Replace this
data.map(function(jsonData) {
with an arrow function, like this
data.map(jsonData => {

React Native can't find variable: navigate

I am doing stack navigation but I can't seem to be able to navigate I will get this error "Can't find variable: navigate" Here is the screenshot of my android emulator
This is my App class(main)
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<Header/>
<AppNavigator/>
</View>
);
}
}
const AppNavigator = StackNavigator({
Cluster1: {
screen: Cluster1,
},
Play: {
screen: Play,
},
});
This is my Cluster1 class
export default class Cluster1 extends Component{
render(){
return(
<View>
<SectionList
renderSectionHeader={({ section }) => {
return (<SectionHeader section={section} />);
}}
sections={ClusterData}
keyExtractor={(item, index) => item.name}
>
</SectionList>
</View>
);
}
}
class SectionHeader extends Component {
render() {
return (
<View style={styles.header}>
<Text style={styles.headertext}>
{this.props.section.title}
</Text>
<TouchableOpacity onPress={() => { navigate("Play");}}>
<Text style ={styles.Play}>Play
</Text>
</TouchableOpacity>
</View>
);
}
}
navigation object only exist in the screen component. (not exist in the nested components). you can pass it into the nested component using props
export default class Cluster1 extends Component{
render(){
return(
<View>
<SectionList
renderSectionHeader={({ section }) => {
return (<SectionHeader navigation={this.props.navigation} section={section} />);
}}
sections={ClusterData}
keyExtractor={(item, index) => item.name}
>
</SectionList>
</View>
);
}
}
class SectionHeader extends Component {
render() {
return (
<View style={styles.header}>
<Text style={styles.headertext}>
{this.props.section.title}
</Text>
<TouchableOpacity onPress={() => { this.props.navigation.navigate("Play");}}>
<Text style ={styles.Play}>Play
</Text>
</TouchableOpacity>
</View>
);
}
}
Include on your SectionHeader the this.props.navigation something like this:
<SectionHeader navigation={this.props.navigation}/>
because the props.navigation are by default on your parent component
and on SectionHeader component you will access to navition like:
..
goToSignUp() {
this.props.navigation.navigate('SignUp');
}
..
For me also was confusing before. Cheers!
You can use this rather than navigate :
this.props.navigation.navigate('Play')
Hope this is helpful.

React Native : Modal closing functionality

I am currently following the modal example given here.
https://facebook.github.io/react-native/docs/modal.html
The code works and it is indeed showing a modal box.
But there is no "close" functionality except the one via TouchableHighlight onPress event.
Is it possible to have a "close modal" functionality via "X" on the corner ?
I checked out the props and I am not able to find any.
So does this mean that using only the TouchableHighlight's onPress event alone you will be able to control the modal's closing ?
App.js code
import React, { Component } from 'react';
import { Modal, Text, TouchableHighlight, View } from 'react-native';
export default class ModalExample extends Component {
state = {
modalVisible: false,
}
setModalVisible(visible) {
this.setState({modalVisible: visible});
}
render() {
return (
<View style={{marginTop: 22}}>
<Modal
animationType="slide"
transparent={false}
visible={this.state.modalVisible}
onRequestClose={() => {alert("Modal has been closed.")}}
>
<View style={{marginTop: 22}}>
<View>
<Text>Hello World!</Text>
<TouchableHighlight onPress={() => {
this.setModalVisible(!this.state.modalVisible)
}}>
<Text>Hide Modal</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
<TouchableHighlight onPress={() => {
this.setModalVisible(true)
}}>
<Text>Show Modal</Text>
</TouchableHighlight>
</View>
);
}
}
import React, { Component } from 'react';
import { Modal, Text, TouchableHighlight, View } from 'react-native';
export default class ModalExample extends Component {
state = {
modalVisible: false,
}
setModalVisible(visible) {
this.setState({modalVisible: visible});
}
closeModal = () => {
this.setState({modalVisible: false})
}
render() {
return (
<View style={{marginTop: 22}}>
<Modal
animationType="slide"
transparent={false}
visible={this.state.modalVisible}
onRequestClose={() => {alert("Modal has been closed.")}}
>
<View style={{marginTop: 22}}>
<View>
<Text>Hello World!</Text>
<TouchableHighlight onPress={() => {
this.setModalVisible(!this.state.modalVisible)
}}>
<Text>Hide Modal</Text>
</TouchableHighlight>
</View>
<CloseButton onPress={this.closeModal} /> // Create your 'X' button with your preferred styling
</View>
</Modal>
<TouchableHighlight onPress={() => {
this.setModalVisible(true)
}}>
<Text>Show Modal</Text>
</TouchableHighlight>
</View>
);
}
}
You just need to add a button to the modal with your preferred styling and on the button's onPress listener set the state variable modalVisible to false for hiding the modal.

Trying to get the modal working in React Native

Attempting to get the modal working on my react native app. I want the more page to display a modal of more options. I have made the following attempt in regards putting the modal in the more menu page. The error I am currently getting is:
MoreMenu.js
import React, { Component } from 'react';
import { Modal, Text, TouchableHighlight, View } from 'react-native';
class MoreMenu extends Component {
state = {
modalVisible: false,
}
setModalVisible(visible) {
this.setState({modalVisible: visible});
}
render() {
return (
<View style={{marginTop: 22}}>
<Modal
animationType={"slide"}
transparent={false}
visible={this.state.modalVisible}
onRequestClose={() => {alert("Modal has been closed.")}}
>
<View style={{marginTop: 22}}>
<View>
<Text>Hello World!</Text>
<TouchableHighlight onPress={() => {
this.setModalVisible(!this.state.modalVisible)
}}>
<Text>Hide Modal</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
<TouchableHighlight onPress={() => {
this.setModalVisible(true)
}}>
<Text>Show Modal</Text>
</TouchableHighlight>
</View>
);
}
}
TabsRoot.JS
class Tabs extends Component {
_changeTab (i) {
const { changeTab } = this.props
changeTab(i)
}
_renderTabContent (key) {
switch (key) {
case 'today':
return <Home />
case 'share':
return <Share />
case 'savequote':
return <SaveQuote />
case 'moremenu':
return <MoreMenu />
}
}
render () {
const tabs = this.props.tabs.tabs.map((tab, i) => {
return (
<TabBarIOS.Item key={tab.key}
icon={tab.icon}
selectedIcon={tab.selectedIcon}
title={tab.title}
onPress={() => this._changeTab(i)}
selected={this.props.tabs.index === i}>
{this._renderTabContent(tab.key)}
</TabBarIOS.Item>
)
})
return (
<TabBarIOS tintColor='black'>
{tabs}
</TabBarIOS>
)
}
}
export default Tabs
You forget to export MoreMenu Component. and you use MoreMenu Component in TabsRoot.js.
pls add following line at the end of MoreMenu.js
export default MoreMenu

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>
);