How to immediately update CSS on state change - javascript

In React Native, I have this component:
<TouchableHighlight onPress={this.selectItem}>
<Text
style={this.getTextIndexStyle()}>
{someText}
</Text>
</TouchableHighlight>
This Text component calls this method to get its styling:
getTextIndexStyle() {
return {
position: 'absolute',
opacity: 0.75,
backgroundColor: this.getTextBoxColor(),
textAlign: 'center',
color: '#ffffff',
fontSize: 20,
fontWeight: 'bold'
};
}
Which in turn calls this method to get its color.
getTextBoxColor() {
if(this.state.highlighted) {
return Constants.HIGHLIGHTED_TEXT_BOX_COLOR;
}
return Constants.UNHIGHLIGHTED_TEXT_BOX_COLOR;
}
Also, when the user clicks the TouchableHighlight, he or she triggers this:
selectItem() {
this.setState({highlighted: true});
}
My problem is that if I click on the TouchableHighlight, the Text component doesn't change its colour.
I'm not sure if this.state is not updated or if it is updated but for some strange reason this.getTextBoxColor() is not called.
Any idea how to make the colour update?

You have an error in the JSX of the onPress of your TouchableHighlight, you can fix it by changing to:
<TouchableHighlight onPress={() => this.selectItem}>
You should also create a StyleSheet and pass the color you wish to it during rendering
const style = (backgroundColor) => (
StyleSheet.create({
textStyle: {
position: 'absolute',
opacity: 0.75,
backgroundColor,
textAlign: 'center',
color: '#ffffff',
fontSize: 20,
fontWeight: 'bold'
})
);
then, on you render method:
render(){
const styles=style(getTextBoxColor())
return(
...
)
}
and on your Text:
<Text
style={styles.textStyle}>
{someText}
</Text>
EDIT: ({backgroundColor}) => (backgroundColor)

Related

Pressables in react-native app wont't work

I have two very simple components and the pressables I have in my Start component just won't work, not the navigation or the console.log(), I can't even inspect them with the element inspector... I am using ImageBackground of react native for the first time so i don't know if this has something to do with it? Although, i did try removing it and i still couldn't press anything...
Here is my code for the Start component:
import React from 'react';
import {ImageBackground, Pressable, StyleSheet, Text, View} from 'react-native';
import { normalize } from '../../utils/helper';
import { colors } from '../../utils/styles';
const image = require('../../assets/images/start-page/start-page-background.png');
export default function Start({navigation}) {
const handleStartPress = () => {
console.log('hi');
navigation.navigate('Home');
};
return (
<View style={styles.container}>
<ImageBackground source={image} style={styles.image}>
<Pressable style={styles.startButton} onPress={() => handleStartPress()}>
<Text style={styles.startText}>Έναρξη</Text>
</Pressable>
<View style={styles.footer}>
<Pressable style={[styles.footerPressable, styles.conditions]}><Text style={styles.footerText}>blah</Text></Pressable>
<Text style={styles.code}>blah</Text>
<Pressable style={[styles.footerPressable, styles.policy]} onPress={() => console.log('policy')}><Text style={styles.footerText}>blah</Text></Pressable>
</View>
</ImageBackground>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
image: {
flex: 1,
},
startButton: {
backgroundColor: colors.main.blue,
borderRadius: normalize(10),
paddingHorizontal: normalize(40),
paddingVertical: normalize(12),
alignSelf: 'center',
position: 'absolute',
bottom: normalize(180),
},
startText: {
color: 'white',
fontSize: normalize(30),
},
footer: {
paddingVertical: normalize(10),
position: 'absolute',
bottom: normalize(15),
},
conditions: {
borderRightColor: 'black',
borderRightWidth: normalize(1),
paddingLeft: normalize(10),
paddingRight: normalize(10),
},
policy: {
paddingLeft: normalize(10),
//zIndex: 999,
},
footerText: {
fontSize: normalize(16),
lineHeight: normalize(16),
color: 'black',
},
code: {
color: colors.main.blue,
fontWeight: '700',
fontSize: normalize(16),
lineHeight: normalize(16),
borderRightColor: 'black',
borderRightWidth: normalize(1),
paddingHorizontal: normalize(10),
},
});
I ran your code and it works fine. But I don't have any more information on your project (such as your RN version), so I can only make some educated guess.
The non-responsiveness can be caused by the other parts of your application that block your JS thread and prevent the event loop from passing message from the queue to the stack.
To debug this, you can toggle the perfMonitor to see if the JS thread frame rate has dropped to 0. You can also try not to render other elements (e.g. render solely this button in your App.tsx) in your app to see if the issue is gone.

React Native: How does this Component call?

Can someone help me with this Component, i want to make like this, but dont know how this white frames called? Can someone tell me this? And if we press that yellow Touchable Opacity it is showing whole Text, and if we press again it will became smaller!
Thanks in Advance , I am Just new in RN
You can easily create that card with a little bit of CSS.
Below is the sample app which shows you how you can achieve that.
Working Example: Expo Snack
import React, { useState, useEffect } from 'react';
import {
Text,
View,
StyleSheet,
FlatList,
Image,
TouchableOpacity,
} from 'react-native';
import { AntDesign } from '#expo/vector-icons';
import Constants from 'expo-constants';
import { newsFeed } from './news';
export default function App() {
const [news, setNews] = useState(newsFeed);
const showFull = (index) => {
const temp = [...news];
temp[index].toggle = !temp[index].toggle;
setNews(temp);
};
return (
<View style={styles.container}>
<FlatList
data={news}
renderItem={({ item, index }) => (
<View style={styles.card}>
<Text style={styles.title}>{item.title}</Text>
<Text style={styles.paragraph}>
{item.toggle ? item.desc : `${item.desc.substr(0, 100)}...`}
</Text>
{item.toggle && (
<Image source={{ uri: item.img }} style={styles.img} />
)}
<View style={styles.bottomBar}>
<Text style={styles.date}>4/02/2021</Text>
<TouchableOpacity onPress={() => showFull(index)}>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text style={styles.moreBtn}>
{!item.toggle ? 'More' : 'Less'}
</Text>
<AntDesign
name={item.toggle ? 'up' : 'down'}
size={12}
color="orange"
/>
</View>
</TouchableOpacity>
</View>
</View>
)}
/>
</View>
);
}
const styles = StyleSheet.create({
bottomBar: {
marginVertical: 5,
flexDirection: 'row',
justifyContent: 'space-between',
},
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
card: {
padding: 10,
backgroundColor: 'white',
marginVertical: 5,
borderRadius: 10,
},
title: {
marginVertical: 5,
fontSize: 18,
fontWeight: 'bold',
},
img: {
flex: 1,
height: 100,
borderRadius: 10,
marginVertical: 5,
},
paragraph: {
fontSize: 14,
},
date: {
fontSize: 12,
color: 'rgba(21,21,21,0.5)',
},
moreBtn: {
fontSize: 12,
color: 'orange',
marginRight: 10,
},
});
actually this card is not a component you can design it using css and if you want to create a component which you can reuse then you can make one component and reuse it as you want and for this card either you can use your own css or a library called native-base which is
like bootstrap but it is used in react-native
you can read about native base here for more information
https://nativebase.io/
and if you want to create card of your own then make a separate file and make a funcional card component in it
and call it wherever you like
import myCustomCard from './card'
and to use it you use like this in your jsx
<myCustomCard />
and if you want to know more about how to pass props and else you can checkout official docs of the react native here
https://reactnative.dev/docs/getting-started

When importing page to App.js it shows up blank

I am fairly new to React Native and am struggling to get this page to show up when importing it to App.js. It was working by itself, but once I tried to clean things up and put the code into its own file and just call upon it, things went south.
To break things down;
Welcome.js contains the code of a "welcome page" I am trying to create
App.js is the default file created that basically just calls Welcome
and GetStartedButton is just the code of a button that is imported into Welcome but I dont think its necessary to provide.
When running App.js I am not receiving any errors, my screen is just white!
Thank you for any help, I appreciate it more than you know. I apologize for my ignorance!
It wouldnt surprise me if it was just another typo.
I am sure my code is horrible btw! Assuming my styles were an interesting way to do things! Learning...
Welcome.js
import React, { Component } from 'react';
import { StyleSheet, Text, View, Button} from 'react-native';
import GetStarted from './src/components/GetStartedButton';
export default class Welcome extends Component {
render() {
return (
<View style={styles.containerMain}>
<View style={styles.containerClub}>
<Text style={styles.title}>Word</Text>
</View>
<View style={styles.containerCaption}>
<Text style={styles.caption}> Words Words Words </Text>
</View>
<View style={styles.containerBottom}>
<GetStarted text='Get Started' color='#E50061' />
</View>
</View>
);
}
}
const styles = StyleSheet.create({
containerMain: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'black',
},
containerClub: {
position: 'absolute',
bottom: 288
},
containerCaption: {
position: 'absolute',
bottom: 250
},
/* To style the button and positioning*/
containerBottom: {
position: 'absolute',
bottom: 100
},
/* To style "Word"*/
title: {
fontSize: 35,
fontWeight: "bold",
},
/* To style "Words Words Words"*/
caption:
{
fontSize: 16
}
}
)
App.js
import React, { Component } from 'react';
import { StyleSheet, Text, View, Button} from 'react-native';
import Welcome from './src/pages/Welcome';
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<Welcome/>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}
}
);
GetStartedButton.js
import React, { Component } from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
const GetStarted = props => {
const content = (
<View style={[styles.button, {backgroundColor: props.color}]}>
<Text style={styles.text}>{props.text}</Text>
</View>
)
return <TouchableOpacity onPress={props.onPress}>{content}</TouchableOpacity>
}
const styles = StyleSheet.create({
button: {
padding: 20,
width: 340,
borderRadius: 8,
alignItems: 'center',
},
text: {
color: 'white',
fontSize: 20,
justifyContent: 'center',
alignItems: 'center',
}
});
export default GetStarted;
The problem is in your Welcome component styles. You colored your texts white, so... it is all white.
const styles = StyleSheet.create({
// (...)
/* To style "word"*/
title: {
color: 'white', // remove it!
fontSize: 35,
fontWeight: "bold",
},
/* To style "words words words"*/
caption:
{
color: 'white', // remove it!
fontSize: 16
}
#edit
Also you did not apply your styles in your App component. It should look like this:
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<Welcome/>
</View>
)
}
}
Try changing backgroundColor to something else other than white like
containerMain: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'black'
},

How can I put in my drawer echo with react-navigation lines in gray below the text?

I would like to do something like this, the only thing I need to know is how to make the gray lines that appear under each component.
By the way I'm using react-navigation.
this is what I want to recreate, I just need to know how to make the intermediate gray line.
Link the Image
My cod:
const DrawerNavigator = createDrawerNavigator({
Example: ScreenExample
},
{
contentComponent: CustomDrawerContentComponent,
drawerWidth: width * 0.63,
contentOptions: {
activeTintColor: blue,
inactiveTintColor: "rgb(105,105,104)",
itemsContainerStyle: {
textAlign: "center"
},
labelStyle: {
fontFamily: "RobotoCondensed-Regular",
fontWeight: "400",
fontSize: 17,
marginLeft: -5
}
},
iconContainerStyle: {
opacity: 1
}
}
const CustomDrawerContentComponent = props => (
<SafeAreaView
style={{ flex: 1, backgroundColor: white }}
forceInset={{ top: "never" }}
>
<SafeAreaView style={{ flex: 0, backgroundColor: "rgb(63,103,149)" }} />
<View
style={{
alignItems: "center",
backgroundColor: "rgb(63,103,149)",
shadowOpacity: 0.3,
shadowOffset: {
height: 5
}
}}
>
<Image
source={require("./src/assets/Icon-Transparente.png")}
style={{ height: 150, width: 150 }}
resizeMode="contain"
/>
</View>
<ScrollView>
<DrawerItems {...props} />
</ScrollView>
</View>
</SafeAreaView>
Just create one common component like this,
import * as React from 'react';
import { View, StyleSheet } from 'react-native';
export default class UnderlinedComponent extends React.Component {
render() {
return (
<View style={{ borderWidth: 1, borderBottomColor: 'grey' }}>
{this.props.children}
</View>
);
}
}
and use it like this,
<UnderlinedComponent>
<Text></Text>
</UnderlinedComponent >
<UnderlinedComponent>
<Button></Button>
</UnderlinedComponent >
this will just create a bottom border, you can customize it as per your need.
and if you don't know how to use contentComponent in a drawer. just see this
I found the answer I was looking for by researching at: https: //reactnavigation.org/docs/en/drawer-navigator.html#contentoptions-for-draweritems
I found that inside the drawer there is a property called itemStyle and use it as follows
itemStyle: {
        borderBottomWidth: 0.5,
        borderBottomColor: gray
      }
with this adding it to contentOptions I could create the lines below the items :)

Get Touch Event on entire screen

I have a disappearing header which I want to bring back into the view on a single tap anywhere on the screen. But if I am wrapping the entire <View> inside a <TouchableX> component the PanResponder stops working. Is there a hack around this?
You do not need to warp it with Touchable component.
Add next props to root View.
onResponderGrant - make View handle touch
onStartShouldSetResponder - make View handle start
To elaborate #Nicholas Chong advice, here is the example that works for me fine. You can use onTouchStart and onTouchEnd handlers on any View via props:
<View
onTouchStart={() => doSomething()}
style={{ width: '100%', height: '100%' }}
/>
More information
onResponderGrant not working for me, and I use onTouchEnd to trigger when tap the screen, this will work
This would be an example of a implementation with a onResponderGrant
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
TouchableOpacity
} from 'react-native';
const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' +
'Cmd+D or shake for dev menu',
android: 'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu',
});
export default class App extends Component<{}> {
constructor() {
super();
this.startTouch = this.startTouch.bind(this);
this.stopTouch = this.stopTouch.bind(this);
this.onTouchE = this.onTouchE.bind(this);
}
startTouch() {
console.debug("You start so don't stop!??");
}
stopTouch() {
console.debug("Why you stop??");
}
onTouchE() {
console.debug("Touchable Opacity is working!!");
}
render() {
return (
<View style={styles.container}
onResponderGrant = { () => this.startTouch() }
onResponderRelease = { () => this.stopTouch() }
onStartShouldSetResponder = { (e) => {return true} }
>
<TouchableOpacity
onPress = { () => this.onTouchE() }
>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
</TouchableOpacity>
<Text style={styles.instructions}>
To get started, edit App.js
</Text>
<Text style={styles.instructions}>
{instructions}
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'cornflowerblue',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
I have included an example of using onResponderGrant and onStartShouldSetResponder inside of a View component.
(Thanks to your previously written answer, #Mr Br)
Definitions
import { Modal, Text, View } from "react-native";
import { useState } from "react";
const [visible, setVisible] = useState(false);
const dismissFunction = () => setVisible(false);
Presentation
<Modal visible={visible} transparent style={{ alignItems: "center", height: "100%", }} >
<View onResponderGrant={dismissFunction} onStartShouldSetResponder={dismissFunction} style={{ flex: 1, backgroundColor: "#1c1c1c75", flexDirection: "column", justifyContent: "flex-end", alignItems: "center" }} >
<View style={{ backgroundColor: "#1E2124", borderRadius: 30, justifyContent: "center", alignItems: "center", height: "30%", shadowColor: "#ffffff10", shadowOpacity: 10, shadowOffset: { width: 0, height: -5 }, width: "101%" }}>
<Text style={{ textAlign: "center", color: "#ffffff", fontSize: 24, marginLeft: "10%", marginRight: "10%", marginBottom: "10%", marginTop: "5%" }}>The message of your modal!</Text>
</View>
</View>
</Modal>
Don't forget to run setVisible(true) somewhere to get the modal to show!

Categories

Resources