I'm recording an app that records exercise logs.
If I click on the area,
I'd like to have items that correspond to that area on the screen.
import React, { Component } from "react";
import {
TouchableOpacity,
StyleSheet,
Text,
View,
FlatList,
} from "react-native";
let clickmenu = "";
class TouchableText extends Component {
render() {
clickmenu = this.props.children.item;
return (
<TouchableOpacity style={styles.text} onPress={this.props.press}>
<Text style={styles.text}>{this.props.children.item.toString()}</Text>
</TouchableOpacity>
);
}
}
class Detail extends Component {
state = {
data: {
chest: [
"플랫 벤치프레스",
"인클라인 벤치프레스",
"케이블 크로스오버",
"푸쉬업",
"딥스",
],
back: ["바벨로우", "데드리프트", "턱걸이", "씨티드 로우", "렛풀 다운"],
},
menu: [
"chest",
"back",
"legs",
"shoulder",
"biceps",
"triceps",
"abs",
"etc..",
],
isclicked: true,
};
press = () => {
this.setState({
isclicked: false,
});
};
render() {
const { data, menu, isclicked } = this.state;
return isclicked ? (
<View style={styles.container}>
<FlatList
data={this.state.menu.map((mp) => {
return mp;
})}
renderItem={(item) => (
<TouchableText press={this.press}>{item}</TouchableText>
)}
/>
</View>
) : (
<View>
{" "}
{(function () {
console.log(this);
if (clickmenu == "가슴") {
<FlatList
data={this.state.data.가슴.map((mp) => {
return mp;
})}
renderItem={(item) => <TouchableText>{item}</TouchableText>}
keyExtractor={(item, index) => index.toString()}
/>;
} else if (state.clickmenu == "등") {
<FlatList
data={this.state.data.등.map((mp) => {
return mp;
})}
renderItem={(item) => <TouchableText>{item}</TouchableText>}
/>;
} else {
console.log("world");
}
})()}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "black",
},
text: { flex: 1, backgroundColor: "white", fontSize: 36, color: "black" },
});
export default Detail;
If I click on the chest button, The following error occurs:
function(){if(){}}
Does this mean class detail in ? How should I solve this?
You are missing a this.
Change
} else if (state.clickmenu == "등") {
to
} else if (this.state.clickmenu == "등") {
You need to set up a constructor with your state attributes within it as such:
class Detail extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
stateAttributesHere: "",
};
}
...
...
}
else if (state.clickmenu == "등") => else if (clickmenu == "등")
Related
I want to know how can I use the "userPrincipalName" on other pages.
what do I need to do to make it work?
in my example, I try to use the "userPrincipalName" object on the MainScreenpage but I don't understand how to do it.
this my example of the Modal page which it has the object "userPrincipalName":
import React,
{ Component } from 'react';
import {
Text,
TouchableOpacity,
StyleSheet,
View,
} from 'react-native';
import Modal from 'react-native-modal';
import PlacesNavigator from '../navigation/PlacesNavigator';
import { LinearGradient } from 'expo-linear-gradient';
import { AzureInstance, AzureLoginView } from 'react-native-azure-ad-2';
const credentials = {
client_id: 'ea00ca9e-8c37-4520-8d80-2c2bb9239bf8',
scope: 'User.Read',
};
export default class Example extends Component {
constructor(props) {
super(props);
this.state = {
visibleModal: 3,
azureLoginObject: {},
loginSuccess: false
};
this.azureInstance = new AzureInstance(credentials);
this._onLoginSuccess = this._onLoginSuccess.bind(this);
}
_renderButton = () => (
<TouchableOpacity
onPress={() => this.setState({ visibleModal: false })}>
<LinearGradient
colors={['#4c669f', '#3b5998', '#192f6a']}
style={{
height: 80,
width: 180,
borderRadius: 10,
backgroundColor: "#2196F3",
justifyContent: 'center',
alignItems: 'center',
marginTop: 50,
}}>
<Text style={{ color: 'white', fontSize: 20, fontWeight: 'bold' }}>כניסה</Text>
</LinearGradient>
</TouchableOpacity>
);
_onLoginSuccess() {
this.azureInstance.getUserInfo().then(result => {
this.setState({
loginSuccess: true,
azureLoginObject: result,
});
console.log(result);
}).catch(err => {
console.log(err);
})
}
renderWelcomeMsg = (currentTime = new Date()) => {
const currentHour = currentTime.getHours()
const splitAfternoon = 12;
const splitEvening = 17;
if (currentHour >= splitAfternoon && currentHour <= splitEvening) {
return 'צהריים טובים,';
} else if (currentHour >= splitEvening) {
return 'ערב טוב,';
}
return 'בוקר טוב,';
}
render() {
if (!this.state.loginSuccess) {
return (
<AzureLoginView
azureInstance={this.azureInstance}
onSuccess={this._onLoginSuccess}
/>)
}
if (this.state.visibleModal === 3) {
const { givenName } = this.state.azureLoginObject;
const { userPrincipalName } = this.state.azureLoginObject;////THIS IS THE OBJECT I WANT
return (
<View style={styles.container}>
<Modal
isVisible={this.state.visibleModal === 3}
animationInTiming={1000}
animationOutTiming={1000}
backdropTransitionInTiming={4000}
backdropTransitionOutTiming={4000}
animationIn={'flipInY'}
>
<LinearGradient
colors={['#43D4FF', 'white']}
style={{ borderRadius: 10 }}>
<View style={styles.modalContent}>
<Text style={{
fontWeight: "bold",
fontSize: 35,
justifyContent: 'center',
alignItems: 'center',
}}>{this.renderWelcomeMsg()} {givenName}
</Text>
<View style={styles.buttonContainer}>
{this._renderButton()}
</View>
</View>
</LinearGradient>
</Modal>
</View>
);
}
return (
<PlacesNavigator />
);
}
}
And this is the MainScreen page that i want to use the object "userPrincipalName" in the Axios:
import React, { Component } from "react";
import {
View,
Text,
StyleSheet,
ActivityIndicator,
Platform,
FlatList,
TouchableOpacity,
TouchableHighlight,
WebView
} from "react-native";
import { HeaderButtons, Item } from "react-navigation-header-buttons";
import HeaderButton from "../components/HeaderButton";
import axios from "axios";
import moment from 'moment'
import storeService from '../components/storeService'
export default class MainScreen extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
userPrincipalName: null
};
}
getData = () => {
this.setState({ isLoading: true, data: [] })
axios.get("https://harigotphat1.mekorot.co.il/ConfirmPackaotWS/OrderApprove/OrderApp_Get_Orders_To_Approve/" + userPrincipalName.split('#')[0])
.then(res => {
this.setState({
isLoading: false,
data: res.data
});
console.log(res.data);
});
}
componentDidMount() {
this.props.navigation.setParams({ getData: this.getData });
// now we load the data we stored in the async storage
storeService.loadKey('userPrincipalName').then((res) => {
console.log("THIS IS THE userPrincipalName", res) //res will contain the value given the key, store this value in your state and use it any where in the component
})
this.getData()
// this.postData()
}
renderItems = (item, index) => {
const { merhavid, yaamID, ezorID, shemEzor } = item;
return (
<TouchableHighlight style={{
backgroundColor: '#ffff78'
}}>
<TouchableOpacity
style={{
paddingVertical: 15,
paddingHorizontal: 10,
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
borderWidth: 0.8,
borderColor: '#d5d7db',
backgroundColor: index % 2 == 0 ? '#d1f0da' : '#f2f5f3',
}}
onPress={() => this.props.navigation.navigate("Info")}>
<Text style={styles.name}>
{ezorID + "" + " |" + " " + merhavid + " " + yaamID + " " + shemEzor}
</Text>
</TouchableOpacity>
</TouchableHighlight>
);
}
render() {
if (this.state.isLoading) {
return (
<View style={{ flex: 0, paddingTop: 300 }}>
<Text style={{ alignSelf: "center", fontWeight: "bold", fontSize: 20 }}>טוען נתונים...</Text>
<ActivityIndicator size={'large'} color={'#08cbfc'} />
</View>
);
}
return (
<>
<View style={styles.container}>
<FlatList
data={this.state.data}
keyExtractor={(_, index) => String(index)}
renderItem={({ item, index }) => { return this.renderItems(item, index) }}
/>
</View>
<View style={styles.bottomMainContainer}>
<View style={styles.bottomView} >
<Text style={styles.bottomTextStyle}>סה"כ: {this.state.data.length} רשומות</Text>
</View>
</View>
</>
);
}
}
This is what React Context was designed for:
Context provides a way to pass data through the component tree without having to pass props down manually at every level.
This also applies to updating data from nested components e.g.
const UserContext = React.createContext({
user: null,
setUser: () => {}
});
function UserContextProvider {
const [user, setUser] = useState(null);
return (
<UserContext.Provider value={{ user, setUser }}>
{props.children}
</UserContext.Provider>
)
}
function App() {
return (
<UserContextProvider>
<MainScreen />
</UserContextProvider>
);
}
class MainScreen extends Component {
static contextType = UserContext;
getData() {
// We should see the user details
console.log(this.context.user);
}
render() {
return (
<div>
<Example />
</div>
)
}
}
class Example extends Component {
static contextType = UserContext
_onLoginSuccess() {
this.azureInstance.getUserInfo().then(result => {
this.setState(...);
// set user in UserContext
this.context.setUser(result);
});
}
}
The best way would be use redux store which helps you create immutable data object which can be update only based on user action https://redux.js.org/basics/store/.
Another simple but not efficient way is to use the react native async storage, Where you store the object and later load it up in the componentDidMount() of your new component.
Another way is to pass these props as ScreenProps in your child component(this is only possible if the screens have a parent child relation)
solution - Sharing the object between components using asnc storage
import AsyncStorage from '#react-native-community/async-storage';
const storeService = {
async saveItem(key, value) {
try {
await AsyncStorage.setItem(key, value);
} catch (error) {
console.log('AsyncStorage Error: ' + error.message);
}
},
loadKey(key) {
return new Promise((resolve, reject) => {
AsyncStorage.getItem(key)
.then(res => {
resolve(res)
})
.catch(err => reject(err));
});
}
};
export default storeService;
Note that these stateless component has 2 methods, One is to save against a key and another is to load.
Now to save a value against a key use
import React,
{ Component } from 'react';
....
export default class Example extends Component {
constructor(props) {
super(props);
....
}
....
render() {
...
if (this.state.visibleModal === 3) {
const { givenName } = this.state.azureLoginObject;
const { userPrincipalName } = this.state.azureLoginObject;
//this is how we will store the value when this component Example loads
storeService.saveItem('userPrincipalName', userPrincipalName)
return (
....
);
}
return (
<PlacesNavigator />
);
}
}
And to load this item again use
import React, { Component } from "react";
...
export default class MainScreen extends Component {
constructor(props) {
super(props);
this.state = {
userPricipalName: null //initialize this state variable
data: []
};
}
getData = () => {
...
var userPrincipalName = this.state.userPrincipalName;
axios.get("https://harigotphat1.mekorot.co.il/ConfirmPackaotWS/OrderApprove/OrderApp_Get_Orders_To_Approve/"+userPrincipalName.split('#')[0])
....
}
componentDidMount() {
// now we load the data we stored in the async storage
storeService.loadKey('userPrincipalName').then((res) => {
this.setState({userPricipalName: res}) //store like this
})
this.getData()
}
...
render() {
....
return (
....
);
}
}
Note that in order to be able to save a whole object in async store you will first need to stringify the object which storing and json parse while reading it again.
Actually i'm new to React and i'm trying to make a simple barcode scanner which show the scanned barcode in an alert and after pressing "OK" in the alert the user should be able to scan another barcode.
The issue is that the barcode is continuously scanned and when the alert is up it's hiding and showing every second the alert.
I was trying to do something like this to show the alert only once and if OK is pressed to be able to show again the alert but only in case the OK is pressed but that had no effect..
onBarCodeRead = (e) => {
if(!this.alertPresent){
this.alertPresent = true;
Alert.alert(
"Barcode type is " + e.type,
"Barcode value is " + e.data,
[
{text: 'OK', onPress: () => this.alertPresent = false;},
],
{cancelable: false},
);
}
}
Here is full code of Barcode.JS
import React, { Component } from 'react';
import { Button, Text, View,Alert } from 'react-native';
import { RNCamera } from 'react-native-camera';
import BarcodeMask from 'react-native-barcode-mask';
class ProductScanRNCamera extends Component {
constructor(props) {
super(props);
this.camera = null;
this.barcodeCodes = [];
this.alertPresent = false;
this.state = {
camera: {
flashMode: RNCamera.Constants.FlashMode.auto,
}
};
}
onBarCodeRead = (e) => {
if(!this.alertPresent){
this.alertPresent = true;
Alert.alert(
"Barcode type is " + e.type,
"Barcode value is " + e.data,
[
{text: 'OK', onPress: () => this.alertPresent = false;},
],
{cancelable: false},
);
}
}
pendingView() {
return (
<View
style={{
flex: 1,
backgroundColor: 'lightgreen',
justifyContent: 'center',
alignItems: 'center',
}}
>
<Text>Waiting</Text>
</View>
);
}
render() {
return (
<View style={styles.container}>
<RNCamera
ref={ref => {
this.camera = ref;
}}
defaultTouchToFocus
flashMode={this.state.camera.flashMode}
mirrorImage={false}
onBarCodeRead={this.onBarCodeRead.bind(this)}
onFocusChanged={() => {}}
onZoomChanged={() => {}}
style={styles.preview}
>
<BarcodeMask/>
</RNCamera>
</View>
);
}
}
The trick here is to modify barcodeTypes props with an internal state.
const defaultBarcodeTypes = [// should be all Types from RNCamera.Constants.BarCodeType];
class ProductScanRNCamera extends Component {
state = {
// your other states
barcodeType: '',
barcodeValue: '',
isBarcodeRead: false // default to false
}
onBarcodeRead(event) {
this.setState({isBarcodeRead: true, barcodeType: event.type, barcodeValue: event.data});
}
// run CDU life-cycle hook and check isBarcodeRead state
// Alert is a side-effect and should be handled as such.
componentDidUpdate() {
const {isBarcodeRead, barcodeType, barcodeValue} = this.state;
if (isBarcodeRead) {
Alert.alert(barcodeType, barcodeValue, [
{
text: 'OK',
onPress: () => {
// Reset everything
this.setState({isBarcodeRead: false, barcodeType: '', barcodeValue: ''})
}
}
]);
}
}
render() {
const {isBarcodeRead} = this.state;
return (
<RNCamera {...your other props} barcodeTypes={isBarcodeRead ? [] : defaultBarcodeTypes}>
<BarcodeMask />
</RNCamera>
)
}
}
A hook version is cleaner
const ProductScanRNCamera = () => {
const [isBarcodeRead, setIsBarcodeRead] = useState(false);
const [barcodeType, setBarcodeType] = useState('');
const [barcodeValue, setBarcodeValue] = useState('');
useEffect(() => {
if (isBarcodeRead) {
Alert.alert(
barcodeType,
barcodeValue,
[
{
text: 'OK',
onPress: () => {
// reset everything
setIsBarcodeRead(false);
setBarcodeType('');
setBarcodeValue('');
}
}
]
);
}
}, [isBarcodeRead, barcodeType, barcodeValue]);
const onBarcodeRead = event => {
if (!isBarcodeRead) {
setIsBarcodeRead(true);
setBarcodeType(event.type);
setBarcodeValue(event.data);
}
}
return (
<RNCamera {...your props}
onBarCodeRead={onBarcodeRead}
barcodeTypes={isBarcodeRead ? [] : defaultBarcodeTypes}>
<BarcodeMask />
</RNCamera>
)
}
use setState in order to set state of component.setState will take the object and update the state of component
check code below
import React, { Component } from 'react';
import { Button, Text, View, Alert } from 'react-native';
import { RNCamera } from 'react-native-camera';
import BarcodeMask from 'react-native-barcode-mask';
class ProductScanRNCamera extends Component {
constructor(props) {
super(props);
this.camera = null;
this.barcodeCodes = [];
this.showAlert = true;
this.state = {
camera: {
flashMode: RNCamera.Constants.FlashMode.auto,
}
};
}
onBarCodeRead = (e) => {
if (this.state.alertPresent) {
this.setState({ showAlert: false });
Alert.alert(
"Barcode type is " + e.type,
"Barcode value is " + e.data,
[
{ text: 'OK', onPress: () =>console.log('ok') },
],
{ cancelable: false },
);
}
}
pendingView() {
return (
<View
style={{
flex: 1,
backgroundColor: 'lightgreen',
justifyContent: 'center',
alignItems: 'center',
}}
>
<Text>Waiting</Text>
</View>
);
}
render() {
return (
<View style={styles.container}>
<RNCamera
ref={ref => {
this.camera = ref;
}}
defaultTouchToFocus
flashMode={this.state.camera.flashMode}
mirrorImage={false}
onBarCodeRead={this.onBarCodeRead.bind(this)}
onFocusChanged={() => { }}
onZoomChanged={() => { }}
style={styles.preview}
>
<BarcodeMask />
</RNCamera>
</View>
);
}
}
I have two components: LeagueSelect and TeamSelect.
All I'm trying to do right now is pass the checkedLeagues state from LeagueSelect to TeamSelect.
It's currently setup to have the checkboxes in TeamSelect be checked if the corresponding league is checked.
The issue: the state passes from LeagueSelect to TeamSelect inconsistently.
This is a video of what it looks like:
https://streamable.com/2i06g
When a box is unchecked, the state updates 'in team', as you can see in the console.log, but, when you try to check the same box again the state does not update in team.
I initially tried to implement this with redux, thought this issue was a redux issue, moved to directly passing state to the child component, and realized that the issue must be somewhere else.
This is my LeagueSelect component:
import React, { Component } from 'react';
import { View, Text, Modal, TouchableHighlight, FlatList, Button } from 'react-native'
import { loadLeagues } from '../actions'
import { connect } from 'react-redux'
import Check from './CheckBox'
import axios from "axios"
import { loadCards, loadTeams, changeLeagues } from '../actions'
import { Icon } from 'native-base'
import TeamSelect from './TeamSelect'
class LeagueSelect extends Component {
constructor(props) {
super(props)
this.state = {
modalVisible: false,
checked: [],
checkedLeagues: [],
checkMessage: ''
}
}
setModalVisible(visible) {
this.setState({modalVisible: visible})
if(this.state.checked.length === 0) {
this.props.league.map(
(v, i) => {
this.state.checked.push(true)
this.state.checkedLeagues.push(v.acronym)
}
)
}
this.setState({ checkMessage: '' })
}
changeCheck = (index, acronym) => {
//local variable to create query param
firstString = []
//adds to local variable if not checked, takes out variable if checked
if(!this.state.checkedLeagues.includes(acronym)) {
firstString.push(acronym)
} else {
firstString.filter(v => { return v !== acronym})
}
//adds leagues that could be in the current state that were not just passed in
this.state.checkedLeagues.map(
(v, i) => {
if(v !== acronym) {
firstString.push(v)
}
}
)
//updates checked leagues state
//makes api call with parameters set
//prevents all leagues being unselected
if(acronym === this.state.checkedLeagues[0] && firstString.length === 0) {
this.setState({ checkMessage: `Don't you want something to look at?` })
} else {
if(!this.state.checkedLeagues.includes(acronym)){
this.state.checkedLeagues[this.state.checkedLeagues.length] = acronym
this.setState({ checkedLeagues: this.state.checkedLeagues })
} else {
newChecked = this.state.checkedLeagues.filter(v => { return v !== acronym})
this.setState({checkedLeagues: newChecked})
}
//updating the check
this.state.checked[index] = !this.state.checked[index]
this.setState({ checked: this.state.checked })
queryString = []
firstString.map(
(v, i) => {
if (queryString.length < 1) {
queryString.push(`?league=${v}`)
} else if (queryString.length >= 1 ) {
queryString.push(`&league=${v}`)
}
}
)
axios.get(`http://localhost:4000/reports${queryString.join('')}`)
.then(response => {
this.props.loadCards(response.data)
})
}
}
render() {
return (
<View style={{ position: 'relative'}}>
<Text
style={{
paddingTop: 8,
paddingLeft: 5,
fontSize: 15
}}
>Leagues</Text>
<View
style={{
flexDirection:"row",
}}
>
{this.props.league === null ?'' : this.props.league.map(
(v, i) => {
return(
<View
key={i}
style={{
alignSelf: 'flex-end',
flexDirection:"row",
top: 4,
}}
>
<Check
checked={this.state.checked[i]}
index={i}
value={v.acronym}
changeCheck={this.changeCheck}
/>
<Text
style={{
paddingLeft: 23,
}}
>{v.acronym}</Text>
</View>
)
}
)}
</View>
<Text
style={{
paddingLeft: 10,
paddingTop: 12,
fontStyle: 'italic',
color: '#F4AF0D'
}}
>{this.state.checkMessage}</Text>
<TeamSelect checkedLeagues={this.state.checkedLeagues}/>
</View>
</View>
);
}
}
export default LeagueSelect
This is my TeamSelect component:
import React, { Component } from 'react'
import { Text, View } from 'react-native'
import { connect } from 'react-redux'
import { loadTeams, loadLeagues } from '../actions'
import Check from './CheckBox'
class TeamSelect extends Component {
constructor(props) {
super(props)
this.state = {
checked: [],
checkedTeams: [],
setOnce: 0
}
}
render() {
console.log('in team', this.props.checkedLeagues)
return(
<View>
{
this.props.team === null ?'' : this.props.team.map(
(v, i) => {
return(
<View key={i}>
<Check
checked={ this.props.checkedLeagues.includes(v.league.acronym) ? true : false }
index={i}
value={v.team_name}
changeCheck={this.changeCheck}
/>
{ v.team_name === undefined ? null :
<Text>{v.team_name}</Text>}
</View>
)
}
)
}
</View>
)
}
}
export default TeamSelect
this.setState({ checkedLeagues: this.state.checkedLeagues })
Statements like these can cause issues as you are mutating and setting the state to the same object. The reference to checked leagues doesn't get updated and react may not trigger a render. Use this instead
this.setState({ checkedLeagues: [...this.state.checkedLeagues] })
But this whole approach to the problem is wrong, you should use one leagues object that has a checked property to it, and pass it down.
make you league object look like this,
const leagues = [
{
acronym: 'abc',
checked: false,
teams: [ ...array of teams here ]
},
...
]
When you pass it down to TeamSelect, you can map it like this
const { leagues } = this.props
{leagues && leagues.map((league, i) => league.teams.map((team, j) (
<View key={team.team_name}>
<Check
checked={league.checked}
index={i + i * j}
value={team.team_name}
changeCheck={() => this.changeCheck(i, j)}
/>
{team.team_name && <Text>{team.team_name}</Text>}
</View>)))}
Same with leagueSelect, you can map leagues like this:
const { leagues } = this.state
{leagues.map((league, i) => (
<View
key={league.acronym}
style={{
alignSelf: 'flex-end',
flexDirection:"row",
top: 4,
}}>
<Check
checked={league.checked}
index={i}
value={league.acronym}
changeCheck={this.changeCheck}
/>
<Text
style={{
paddingLeft: 23,
}}
>{league.acronym}</Text>
</View>
)
)}
Note: leagues have to be copied from props to state for you to mutate it. I just typed this so it will need some changes before it runs, it's just meant to show you the "react way" of coding this.
https://reactjs.org/docs/lifting-state-up.html
I am creating country codes class. In which, I return list of country codes. I want to close modal that contains of list codes and also return the clicked item value of flat list that display list of modals.
I want return country code from modal screen to current js file. Here is my Codes modal Class:-
import React, { Component } from 'react';
import { StyleSheet, View,
Text,Modal,FlatList,TouchableWithoutFeedback} from 'react-native';
import { showMessage } from '../utils/GeneralFunctions';
import { Icon } from 'react-native-elements';
import TextInputBox from '../components/TextInputBox';
import {color} from '../values/color';
import {TextViewNonClickable} from '../components/TextView';
const countryCodes = require('../jsonData/codesCountry.json');
export default class Codes extends Component {
constructor(props) {
super(props);
this.state = {
countryCodes : countryCodes,
modalVisible : false,
searchedText : '',
loading : false,
selectedCountry : '',
};
this.arrayHolder = [];
}
componentWillMount = () => {
if(this.state.modalVisible == false){
this.setState({countryCodes : countryCodes})
}
this.arrayHolder = countryCodes;
};
//show countries modal
static showCountryModal = (modalVisibility) => {
showMessage("sunny");
if(modalVisibility == true){
this.setState({modalVisible:false})
}else{
this.setState({modalVisible:true})
}
}
//set Modal Visibility
static setModalVisibility(visibility){
showMessage("Set Modal Visibility : "+visibility);
this.setState({modalVisible:visibility});
}
//search country
searchText = (text) => {
const newData = this.arrayHolder.filter(item => {
const itemData = `${item.name.toUpperCase()}
${item.code.toUpperCase()} ${item.dial_code.toUpperCase()}`;
const textData = text.toUpperCase();
return itemData.indexOf(textData) > -1;
});
if(text != null){
this.setState({
countryCodes : newData,
});
}else if(text == " "){
this.setState({
countryCodes : countryCodes,
});
}
};
//setting selected country
selectedCountry = (item) => {
this.props.modalVisible = false;
this.setState({selectedCountry : item.dial_code})
showMessage("Code : " + item.dial_code)
}
_renderItem = ({item}) => {
return (
<TouchableWithoutFeedback onPress={() =>
this.selectedCountry(item)}>
<View style=
{{height:48,flexDirection:'row',
justifyContent:'center',alignItems:'center',
padding:16,borderBottomWidth:1,
borderBottomColor:color.pageBackground}}>
<TextViewNonClickable
textViewText={item.name+"("+item.code+")"}
textStyle=
{{fontSize:16,fontWeight:'bold',flex:0.85,
color:color.colorBlack}}
/>
<TextViewNonClickable
textViewText={item.dial_code}
textStyle=
{{fontSize:16,fontWeight:'bold',flex:0.15,
color:color.colorBlack}}
/>
</View>
</TouchableWithoutFeedback>
)
}
render() {
// const {modalVisible} = this.props;
return (
<Modal
animationType='slide'
transparent={false}
visible={this.state.modalVisible}
onRequestClose={() => this.setState({
countryCodes : countryCodes})}
>
<View>
<View style={{flexDirection:'row',height:48,
justifyContent:"center",alignItems:'center',
borderBottomWidth:1,paddingStart:16,paddingRight:16}}>
<Icon
name='search' type='material-icons'
size={24} color='black'
/>
<TextInputBox
textInputStyle=
{{borderColor:color.colorTransparent,
color:color.colorHintText,flex:1}}
placeHolderText='Search here...'
onChangeText={text =>
this.searchText(text)}
/>
</View>
<View>
<FlatList
data={this.state.countryCodes}
renderItem={this._renderItem}
keyExtractor={(item,index) =>
item+index}
showsVerticalScrollIndicator={false}
/>
</View>
</View>
</Modal>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
Here is my codesClass.js class
import React, { Component } from 'react';
import {StyleSheet,View,ImageBackground} from 'react-native';
import { HeaderView } from '../components/Headers';
import { Actions } from 'react-native-router-flux';
import { appString } from '../values/appStrings';
import { color } from '../values/color';
import TextInputBox from '../components/TextInputBox';
import TextViewClickable from '../components/TextView';
import Button from '../components/Buttons';
import {showToast, showMessage} from '../utils/GeneralFunctions'
import { dimension } from '../values/dimensions';
import Codes from '../dialogs/Codes';
export default class SignUpScreen extends Component {
constructor(props) {
super(props);
this.state = {
countryCode : '',
phone : '',
modalVisible:false,
};
}
openOrCloseCountryCodes = () => {
if(this.state.modalVisible == false){
// this.setState({modalVisible:true});
Codes.setModalVisibility(true);
}else{
// this.setState({modalVisible:false});
Codes.setModalVisibility(false);
}
// Codes.showCountryModal(true);
}
render() {
return (
<View>
<View style={{flexDirection:'row',marginTop:20}}>
<TextViewClickable
textViewText={this.state.countryCode != '' ?
this.state.countryCode : '+91'}
touchableButtonStyle={styles.touchableButtonStyle}
textStyle={styles.textStyle}
onPress={() =>
{this.openOrCloseCountryCodes();}}
/>
<TextInputBox
placeHolderText={appString.placeholderPhoneNumber}
onChangeTextSet={(text) => {this.setState({
phone : text})}}
textInputStyle={{flex : 1,marginLeft : 4}}
/>
</View>
<Codes modalVisible={this.state.modalVisible}
closeModal={() => this.openOrCloseCountryCodes()}/>
</View>
);
}
}
const styles = StyleSheet.create({
parentView : {
flex: 1,
alignItems: 'center',
},
touchableButtonStyle: {
marginRight : 4,
borderRadius: dimension.textInputBorderRadius,
borderWidth: dimension.textInputBorderWidth,
borderColor: color.textInputBorderColor,
justifyContent : 'center',
alignItems:'center',
paddingLeft: 16,
paddingRight: 16,
},
textStyle : {
fontSize: dimension.regularFontSize,
color : color.colorHintText,
}
});
onRequestClose on Modal should be:
onRequestClose={() => this.props.closeModal(this.state.selectedCountry)}
and SignUpScreen, handle callback value:
<Codes
modalVisible={this.state.modalVisible}
closeModal={(selectedCountry) => {
this.openOrCloseCountryCodes()
// do something with selectedCountry
console.log(selectedCountry)
}}
/>
In your case I assume the closing and opening of Modal is working.
In the below function you set the selected country code to a certain state along with it close the modal and pass the value to class Codes create another function same as showCountryModal and set it to a state there.
In class signUpScreen paste the below changes
Code below :
selectedCountry = (item) => {
this.openOrCloseCountryCodes();
Codes. setSelectedCountryCode(item.dial_code);
this.setState({selectedCountry : item.dial_code})
showMessage("Code : " + item.dial_code)
}
In class Codes paste the below changes
Code below :
// initialise `state` `countryCode`
constructor(props) {
super(props);
this.state = {
countryCodes : countryCodes,
modalVisible : false,
searchedText : '',
loading : false,
selectedCountry : '',
countryCode: ""
};
this.arrayHolder = [];
}
//set selected country
static setSelectedCountryCode = (countryCode) => {
this.setState({countryCode: countryCode})
}
Also include onRequestClose so that backbuttonclick of android gets handled
on onRequestClose call the function to close the modal
You should study the concept of props and the static method idea not that great to control modal visibility use props instead.
Im pretty new in React Native (and Javscript) and im trying to understand react native navigation.
I have a homeScreen, and in this screen there is a CardFlatList, which has several CardComponents. If i click on a CardComponent, a Detail Page should open and represent the information of the cardComponent.
First I tried the navigation with a button in the homeScreen and it worked. But i don't know how to pass the navigator from homescreen -> CardFlatList -> CardComponent (onPress).
My CardComponent
export default class CardComponent extends Component {
constructor(props) {
super(props)
}
render() {
return (
<View style={styles.container}>
<Card
featuredTitle={this.props.eventname}
featuredSubtitle={this.props.eventveranstalter}
image={{uri: this.props.eventimage}}
>
<View style={styles.chipContainer}>
<ChipsComponent text={this.props.eventtag1} style={{ marginBottom: 10 }} />
<ChipsComponent text={this.props.eventtag2} style={{ marginBottom: 10 }} />
<ChipsComponent text={this.props.eventtag3} style={{ marginBottom: 10 }} />
</View>
<View style={styles.cardaction}>
<Text style={styles.cardfooter}>
{this.props.eventuhr}
</Text>
<Text style={styles.cardfooter}>
{this.props.eventort}
</Text>
<Button
backgroundColor='#5ac8fa'
fontFamily='Arial'
fontWeight='bold'
buttonStyle={styles.buttonfooter}
title='Teilnehmen' />
</View>
</Card>
</View>
)
}
My homeScreen
export default class homeScreen extends Component {
static navigationOptions = {
drawerLabel: 'Home',
headerMode: 'none',
};
constructor(props) {
super(props)
}
render() {
var {navigate} = this.props.navigation;
return (
<View style={styles.containerAll}>
<Navigationbar onPressBar={()=>this.props.navigation.navigate('DrawerOpen')} />
<View style={styles.container}>
<CardFlatList navigation={this.props.navigation} />
</View>
</View>
);
}
}
my router.js
export const DrawNavigation = DrawerNavigator({
Home: {
screen: homeScreen
},
Notifications: {
screen: test,
},
});
export const Root = StackNavigator({
DrawNavigation: {
screen: DrawNavigation,
navigationOptions: {
header: false,
},
},
First: { screen: homeScreen },
Second: { screen: eventDetailScreen },
});
import React, { Component } from "react";
import { View, Text, FlatList, ActivityIndicator,Image } from "react-native";
import { List, ListItem, SearchBar } from "react-native-elements";
import CardComponent from './CardComponent';
function getCardComponentArray() {
var texts = ['1', '2', '3', '4', '5'];
var cardComponents = texts.map((text) => <CardComponent title={text} />);
return cardComponents;
}
function getData() {
var texts = ['1', '2', '3', '4', '5'];
return texts
}
class CardFlatList extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
data: [],
page: 1,
seed: 1,
error: null,
refreshing: false
};
}
componentDidMount() {
this.makeRemoteRequest();
}
makeRemoteRequest = () => {
this.setState({
data: getData(),
error: null,
loading: false,
refreshing: false
});
};
handleRefresh = () => {
this.setState(
{
page: 1,
seed: this.state.seed + 1,
refreshing: true
},
() => {
this.makeRemoteRequest();
}
);
};
handleLoadMore = () => {
this.setState(
{
page: this.state.page + 1
},
() => {
this.makeRemoteRequest();
}
);
};
renderSeparator = () => {
return (
<View
style={{
height: 2,
}}
/>
);
};
renderHeader = () => {
return <SearchBar placeholder="Type Here..." lightTheme round />;
};
renderFooter = () => {
if (!this.state.loading) return null;
return (
<View
style={{
paddingVertical: 20,
borderTopWidth: 1,
}}
>
<ActivityIndicator animating size="large" />
</View>
);
};
render() {
return (
// <List>
<FlatList
data={this.state.data}
renderItem={({ item }) => (
<CardComponent
eventname={'Halloween'}
eventveranstalter={'park'}
eventuhr={'17:00'}
eventort={'berlin'}
eventimage={'http://whatstonightapp.com/wp-content/uploads/2016/12/background_light-1.jpg'}
eventtag1={'party'}
eventtag2={'music'}
eventtag3={'dance'}
>
</CardComponent>
)}
keyExtractor={item => item.email}
ItemSeparatorComponent={this.renderSeparator}
// ListHeaderComponent={this.renderHeader}
ListFooterComponent={this.renderFooter}
onRefresh={this.handleRefresh}
refreshing={this.state.refreshing}
onEndReached={this.handleLoadMore}
onEndReachedThreshold={50}
/>
// </List>
);
}
}
export default CardFlatList;
You can do it as following.
render() {
return (
// <List>
<FlatList
data={this.state.data}
renderItem={({ item }) => (
<CardComponent
navigation={this.props.navigation}
eventname={'Halloween'}
eventveranstalter={'park'}
eventuhr={'17:00'}
eventort={'berlin'}
eventimage={'http://whatstonightapp.com/wp-content/uploads/2016/12/background_light-1.jpg'}
eventtag1={'party'}
eventtag2={'music'}
eventtag3={'dance'}
>
</CardComponent>
)}