React Native elements not rendering as expected - javascript

I am just getting started with React Native. I have created a new App using expo.io and am currently testing the components provided by https://react-native-elements.github.io
I am trying out input forms and buttons my code currently looks like this:
class EnterNewPasswordComp extends React.Component {
constructor(props) {
super(props);
this.state = {
pass : ''
}
}
render() {
return <View style={styles.container}>
<Text style={styles.label}>{pass_label}</Text>
<Input placeholder='Password' />
<Text style={styles.note}>{pass_desc}</Text>
<Button title="Submit" type="outline" />
</View>;
}
}
const styles = {
container : {
flex : 1,
justifyContent: 'center',
alignItems: 'center',
},
label : {
fontSize: 20,
},
note : {
fontSize: 12,
marginBottom: 20
},
input : {
color : style.txtcolor
},
btn : {
width : '50%'
}
};
the component (currently) only returning the EnterNewPasswordComp
class IndexComponent extends React.Component {
constructor(props) {
super(props);
this.passDao = Factory.getPasswordDao();
this.state = {
status: 'initializing'
}
}
async componentDidMount() {
try {
const pass = await this.passDao.getPassword();
logger.info(pass);
const setupNeeded = pass === null;
if( setupNeeded ) {
this.setState({
status : 'setup'
});
}
else {
this.setState({
status : 'ready'
})
}
} catch (e) {
logger.error("Error during db query", e);
this.setState({
status: 'corrupted'
});
}
}
render() {
let msg = "initializing";
switch (this.state.status) {
case 'initializing':
msg = 'initializing';
break;
case 'corrupted':
default:
msg = 'corrupted';
break;
case 'ready':
msg = 'ready';
break;
case 'setup':
return <EnterNewPasswordComp/>
}
return <Text>{msg}</Text>
}
}
and this component is used in my App.js like this:
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<IndexComponent/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
}
});
This is how my output looks like on my Android Phone:
Note that:
The input field is not rendering at all
The button type outline is not picked up correctly
The button width is not picked up correctly
I played around with the styles, (like setting the color of the input-form, suspecting it might be the same as the background), but nothing changed at all. I am wondering if I am doing something fundamentally wrong to produce those issues.

Related

How to handle volumes of multiple track in react-native sound, i want to play 2 sound together and if i want to decrease sound of one

Here is my code screen code
import React, {Component} from 'react';
import {StyleSheet, Text, TouchableOpacity, View, ScrollView, Alert} from 'react-native';
import Sound from 'react-native-sound';
import BgSoundPlayer from '../../../../Components/BgSoundPlayer/BgSoundPlayer';
const audioTests = [
{
title: 'mp3 remote download',
url: 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3',
},
{
title: "mp3 remote - file doesn't exist",
url: 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-9.mp3',
},
];
const Button = ({title, onPress}) => (
<TouchableOpacity onPress={onPress}>
<Text style={styles.button}>{title}</Text>
</TouchableOpacity>
);
const Header = ({children, style}) => <Text style={[styles.header, style]}>{children}</Text>;
const Feature = ({
title,
onPress,
buttonLabel = 'PLAY',
status,
volumeIncrease,
volumeDecrease,
}) => (
<View style={styles.feature}>
<Header style={{flex: 1}}>{title}</Header>
{status ? <Text style={{padding: 5}}>{resultIcons[status] || ''}</Text> : null}
<Button title={buttonLabel} onPress={onPress} />
<Button title="Volume Increase" onPress={volumeIncrease} />
<Button title="volume Decrease" onPress={volumeDecrease} />
</View>
);
const resultIcons = {
'': '',
pending: '?',
playing: '\u25B6',
win: '\u2713',
fail: '\u274C',
};
function setTestState(testInfo, component, status) {
component.setState({tests: {...component.state.tests, [testInfo.title]: status}});
}
/**
* Generic play function for majority of tests
*/
function playSound(testInfo, component) {
setTestState(testInfo, component, 'pending');
BgSoundPlayer.setSound(testInfo);
}
class MainView extends Component {
constructor(props) {
super(props);
Sound.setCategory('Playback', true); // true = mixWithOthers
// Special case for stopping
this.stopSoundLooped = () => {
if (!this.state.loopingSound) {
return;
}
this.state.loopingSound.stop().release();
this.setState({
loopingSound: null,
tests: {...this.state.tests, ['mp3 in bundle (looped)']: 'win'},
});
};
this.state = {
loopingSound: undefined,
tests: {},
};
}
render() {
return (
<View style={styles.container}>
<ScrollView style={styles.container} contentContainerStyle={styles.scrollContainer}>
{audioTests.map(testInfo => {
return (
<Feature
status={this.state.tests[testInfo.title]}
key={testInfo.title}
title={testInfo.title}
onPress={() => {
playSound(testInfo, this);
}}
volumeIncrease={() => {
BgSoundPlayer.increaseVolume();
}}
volumeDecrease={() => {
BgSoundPlayer.decreaseVolume();
}}
/>
);
})}
<Feature
title="mp3 in bundle (looped)"
buttonLabel={'STOP'}
onPress={() => {
BgSoundPlayer.pouse();
}}
/>
</ScrollView>
</View>
);
}
}
export default MainView;
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'gray',
},
scrollContainer: {},
title: {
fontSize: 20,
fontWeight: 'bold',
paddingTop: 30,
padding: 20,
textAlign: 'center',
backgroundColor: 'rgba(240,240,240,1)',
},
button: {
fontSize: 20,
backgroundColor: 'rgba(220,220,220,1)',
borderRadius: 4,
borderWidth: 1,
borderColor: 'rgba(80,80,80,0.5)',
overflow: 'hidden',
padding: 7,
},
header: {
textAlign: 'left',
},
feature: {
padding: 10,
borderTopWidth: 1,
borderBottomWidth: 1,
},
});
And my BgSoundPlayer file
import {Alert} from 'react-native';
import Sound from 'react-native-sound';
Sound.setCategory('Playback', true);
class BgSoundPlayer1 {
setSound(soundURL) {
try {
this.soundURL = soundURL;
if (soundURL.isRequire) {
this.soundRef = new Sound(soundURL.url, error =>
this.callback(error, this.soundRef),
);
} else {
this.soundRef = new Sound(soundURL.url, Sound.MAIN_BUNDLE, error =>
this.callback(error, this.soundRef),
);
}
} catch (error) {
console.log('SOUNDREFERROR::', error);
}
}
callback(error, sound) {
try {
if (error) {
Alert.alert('error', error.message);
return;
}
//this.soundURL.onPrepared && this.soundURL.onPrepared(sound);
sound.play(() => {
sound.release();
});
} catch (error) {
console.log('CALL_BACKERROR::', error);
}
}
getVolume() {
return this.soundRef?.getVolume();
}
increaseVolume(soundURL) {
console.log('CHECKREF', this.soundRef);
let sound = this.soundRef?.getVolume();
if (sound < 1 || sound == 1) {
this.soundRef?.setVolume(sound + 0.1);
}
}
decreaseVolume(soundURL) {
console.log('CHECKREF', this.soundRef);
let sound = this.soundRef?.getVolume();
if (sound > 0 || sound == 0) {
this.soundRef?.setVolume(sound - 0.1);
}
}
pouse() {
this.soundRef?.pause();
}
}
const BgSoundPlayer = new BgSoundPlayer1();
export default BgSoundPlayer;
So what is happening right now if, when I am playing one audio track and increasing decreasing volume of track its working fine
but problem occurre's when I play second track and decrease sound of first one, it dosent works it decrease volume of second track
but when I tried to debug problem, I got to know that my this.soundRef variable is taking the refrance of latest one sound, so how can solve this

React native - is there a way to use an object from another page?

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.

Why is socket.on() from a previous screen component executed?

I have two react components. the first Lobby uses react-native-navigation to push Gameroom to the stack. It passes props such as the socket object and other data to the Gameroom component
when the back button of the navigation bar is pressed inside Gameroom, a socket.io leave event is emitted, and I have verified it is heard by the server, so the socket passed through props works. the server then emits an event left back to the socket.io room (Gameroom component).
the left event listener, if placed inside Gameroom's componentDidMount() does not execute. However, if the same socket.io event listener is placed in Lobby component (previous screen) componentDidMount() the event is heard
I've tried adding the event listener to multiple componentDidMount functions, I also thought about using the Context API, but I'm not working with nested components. I'm passing the socket object in react-native-navigation's {passProps} from screen to screen
Lobby:
imports ...
const socket = io("http://192.xxx.xxx.xx:3000");
export default class Lobby extends React.Component {
static options(passProps) {
return {
topBar: {
background: {
color: "transparent"
},
drawBehind: true,
visible: true,
animate: true,
leftButtons: [
{
id: "leave",
icon: require("../assets/img/Chevron.png")
}
]
}
};
}
constructor(props) {
super(props);
this.state = {
username: "Initializing...",
queue: []
};
}
componentDidMount() {
Navigation.events().bindComponent(this);
socket.emit("lobbyEntry");
socket.on("lobbyEntry", entry => {
this.setState({ queue: entry.lobby, username: socket.id });
});
socket.on("userJoined", lobby => {
this.setState({ queue: lobby });
});
// socket.on("left", () => {
// alert("Opponent Left...Oh well");
// Navigation.pop(this.props.componentId);
// });
}
navigationButtonPressed({ buttonId }) {
switch (buttonId) {
case "leave":
socket.emit("leave");
Navigation.popToRoot(this.props.componentId);
break;
}
}
createMatch = () => {
if (this.state.username != "Initializing...") {
socket.emit("findMatch");
socket.on("alreadyCreated", () => {
alert("You already created a match!");
});
socket.on("listUsers", lobby => {
this.setState({ queue: lobby });
});
socket.on("matchFound", data => {
Navigation.push(this.props.componentId, {
component: {
name: "Gameroom",
passProps: {
room: data.id,
socket: socket,
firstMove: data.firstMove,
p1: data.p1,
p2: data.p2
}
}
});
});
} else {
alert("Wait for Username to be initialized...");
}
};
render() {
const bg = getBackground();
return (
<ImageBackground source={bg} style={{ height: "100%", width: "100%" }}>
<View style={styles.title_container}>
<Text style={styles.title_sm}>Matchmaking Lobby</Text>
</View>
<View style={styles.alt_text_container}>
<Text style={styles.alt_text_md}>Username:</Text>
<Text style={styles.alt_text_md}>{this.state.username}</Text>
</View>
<View
style={{
flexDirection: "column",
justifyContent: "center",
alignItems: "center"
}}
>
<XplatformButton onPress={this.createMatch} text={"Create a Match"} />
</View>
<View style={styles.alt_text_container}>
<Text style={styles.alt_text_sm}>Players actively searching...</Text>
<FlatList
style={styles.alt_text_container}
data={this.state.queue}
renderItem={({ item, index }) => (
<Text style={styles.alt_text_md} key={index}>
{item}
</Text>
)}
/>
</View>
</ImageBackground>
);
}
}
Gameroom:
import ...
export default class Gameroom extends React.Component {
static options(passProps) {
return {
topBar: {
title: {
fontFamily: "BungeeInline-Regular",
fontSize: styles.$navbarFont,
text: "Gameroom - " + passProps.room,
color: "#333"
},
background: {
color: "transparent"
},
drawBehind: true,
visible: true,
animate: true,
leftButtons: [
{
id: "leave",
icon: require("../assets/img/Chevron.png")
}
]
}
};
}
constructor(props) {
super(props);
Navigation.events().bindComponent(this);
}
navigationButtonPressed({ buttonId }) {
switch (buttonId) {
case "leave":
this.props.socket.emit("leave");
Navigation.pop(this.props.componentId);
break;
}
}
componentDidMount() {
// socket.on("left", () => {
// alert("Opponent Left...Oh well");
// Navigation.pop(this.props.componentId);
// });
}
render() {
const bg = getBackground();
return this.props.p2 != null ? (
<Gameboard
room={this.props.room}
you={
this.props.socket.id == this.props.p1.username
? this.props.p1.marker
: this.props.p2.marker
}
opponent={
this.props.socket.id != this.props.p1.username
? this.props.p2.marker
: this.props.p1.marker
}
move={this.props.firstMove}
socket={this.props.socket}
/>
) : (
<ImageBackground style={styles.container} source={bg}>
<View style={{ marginTop: 75 }}>
<Text style={styles.alt_text_md}>
Waiting for Opponent to Join...
</Text>
</View>
</ImageBackground>
);
}
}
I expect the event listener to execute from the current screen's componentDidMount() function, but it only executes if it's inside the previous screen's componentDidMount()
When you create a component,
the constructor -> componentWillMount -> render -> componentDidMount is
followed.
In your Lobby class, the event listener is run because it is in ComponentDidmont.
However, the event listener of the Gameroom class is inside the constructor. If executed within the constructor, the event cannot be heard because it is not yet rendered.
Event listeners are called when they appear on the screen
Usage
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}
componentWillUnmount() {
// Not mandatory
if (this.navigationEventListener) {
this.navigationEventListener.remove();
}
}

How to close modal and return value from flatlist when click on item in react native?

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.

React Native Display Rendering

I updated the code to reflect Denis' solution. However, react is now no longer responding to commands sent from the node server
export default class Display extends Component {
constructor(props){
super(props);
this.state = {
ren: "",
action: "background",
media: "white",
backgroundColor: 'white',
uri: "https://www.tomswallpapers.com/pic/201503/720x1280/tomswallpapers.com-17932.jpg"
};
}
componentDidMount(){
this.startSocketIO();
}
componentWillUnmount(){
socket.off(Socket.EVENT_CONNECT);
}
startSocketIO(){
socket.on('function_received', func_var => {
let command = func_var.split(" ");
this.setState({action: command[0]});
this.setState({media: command[1]});
console.log(this.state.action);
console.log(this.state.media);
switch(this.state.action){
case 'image':
this.setState({ uri: this.state.media});
console.log(this.state.uri);
case 'background':
this.setState({ backgroundColor: this.state.media});
console.log(this.state.backgroundColor);
default:
console.log(this.state.backgroundColor);
// return (<View style={{backgroundColor: this.state.backgroundColor, flex: 1}} />);
}
});
}
render(){
return (
null
);
}
}
I'm currently working on a basic react native app that displays images received in uri format from a node server and changes the background color. Separately, both of my implementations work. (See the BackGround and ImageServer components) I'm now attempting to combine the functionality of both components into one component named display. So far my current code looks like it should work without issue however after sending a command to the device via socket.io it appears that the render doesn't go any further since my console logs stop populating after a test. I'm not sure if there is an issue with the setup of the switch statement or if I'm somehow causing a race condition. Any insight would be greatly appreciated!
import React, { Component } from 'react';
import {Image, Text, StyleSheet, Button, View, Dimensions, Vibration} from 'react-native';
const io = require('socket.io-client');
//change this to your public ip "google what is my ip address"
//This will be modified in the future to grab the ip address being used by
//the node server
let server = 'redacted';
let socket = io(server, {
transports: ['websocket']
});
export default class Display extends Component {
constructor(props){
super(props);
this.state = {
action: "background",
media: "white",
backgroundColor: 'white',
uri: "https://www.tomswallpapers.com/pic/201503/720x1280/tomswallpapers.com-17932.jpg"
};
}
render(){
socket.on('function_received', func_var => {
var command = func_var.split(" ");
this.setState({action: command[0]});
this.setState({media: command[1]});
});
console.log(this.state.action);
console.log(this.state.media);
switch(this.state.action){
case 'image':
this.setState({ uri: this.state.media});
return (
<Image
source={{uri: this.state.uri}}
style={styles.fullscreen} />
);
case 'background':
this.setState({ backgroundColor: this.state.media});
return (<View style={{backgroundColor: this.state.backgroundColor, flex: 1}} />);
default:
return (<View style={{backgroundColor: this.state.backgroundColor, flex: 1}} />);
}
}
}
export class BackGround extends Component {
constructor(props){
super(props);
this.state = {
backgroundColor: 'black'
};
}
render(){
socket.on('function_received', func_var => {
this.setState({ backgroundColor: func_var});
});
return (
<View style={{backgroundColor: this.state.backgroundColor, flex: 1}} />
);
}
}
export class ImageServer extends Component {
constructor(props){
super(props);
this.state = {
uri: "https://www.tomswallpapers.com/pic/201503/720x1280/tomswallpapers.com-17932.jpg"
};
}
render() {
socket.on('function_received', func_var => {
//Vibration.vibrate([0, 500, 200, 500,200,500,200,500,200,500,200,500,200], false);
this.setState({ uri: func_var});
});
return(
<Image
source={{uri: this.state.uri}}
style={styles.fullscreen}
/>
);
}
}
You code should like this
componentDidMount() {
this.startSocketIO();
}
startSocketIO() {
socket.on('some_method', (response) => {
this.setState({ key: response.some_value })
});
}
componentWillUnmount() {
// unsubscribe socket.io here !important
}
render() {
return (
// JSX
);
}

Categories

Resources