Related
CardItem receives the cardIsLocked prop, which changes frequently and depends on user actions.
TouchableOpacity, that affected by this prop, reflects all app state correctly all the time. I can or can't press on it accordingly to my expectations. That is why I know that its disabled prop re-renders well. But prop style of top View component - doesn't.
So, all interaction works as demanded but styles not re-renders. How could this difference be possible during usage of the same prop cardIsLocked?
Thanks for ideas.
const CardItem = (props) => {
const card = props.card;
const cardIsLocked = props.cardIsLocked;
const handler = props.handler.bind(this, { card });
return (
<View style={cardIsLocked // <-- not causes re-renders
? styles.cardLocked
: styles.cardActive}>
<TouchableOpacity
disabled={cardIsLocked} // <-- causes re-renders
style={styles.innerCardSpace}
onPress={handler}
>
<View style={styles.card}>
<Text style={styles.text}>{card.cardName}</Text>
</View>
</TouchableOpacity>
</View>
);
};
export default CardItem;
const styles = StyleSheet.create({
cardActive: {
padding: 1,
borderWidth: 1,
borderRadius: 3,
maxWidth: 30,
minWidth: 30,
height: 50,
borderColor: "#00ee00",
},
cardLocked: {
padding: 1,
borderWidth: 1,
borderRadius: 3,
maxWidth: 30,
minWidth: 30,
height: 50,
borderColor: "#black",
},
innerCardSpace: {
flex: 1,
justifyContent: "center",
alignContent: "center",
flexDirection: "column",
margin: 1,
},
card: {
height: 26,
width: 46,
alignItems: "center",
backgroundColor: "#white",
},
text: { fontWeight: "700", fontSize: 10 },
});
Just to formalize the answer.
The error is the # at the beginning of the color's name.
The # must be used when declaring code RGB like #eeff00. For colors declared as names the # isn't necessary
So the re-rendering is occurring. But the problem is when any attribute of style has an unacceptable format, React doesn't apply it, and tries to keep the last identical attribute or will do nothing.
The code fixed
const styles = StyleSheet.create({
cardActive: {
padding: 1,
borderWidth: 1,
borderRadius: 3,
maxWidth: 30,
minWidth: 30,
height: 50,
borderColor: "#00ee00",
},
cardLocked: {
padding: 1,
borderWidth: 1,
borderRadius: 3,
maxWidth: 30,
minWidth: 30,
height: 50,
borderColor: "black",
},
innerCardSpace: {
flex: 1,
justifyContent: "center",
alignContent: "center",
flexDirection: "column",
margin: 1,
},
card: {
height: 26,
width: 46,
alignItems: "center",
backgroundColor: "white",
},
text: { fontWeight: "700", fontSize: 10 },
});
I have a Functional Component and I am trying to get data from an axios.get() and render some components dynamically based on the response of the request.
If I console.log the response is Ok, but my problem is how to use the return from axios.get() to create components on the screen.
I've tried with a simple array and using it I can create the components. What I want is to create the components on screen the same way I've done with the array.
I've read a lot of post before posting my own. I would really appreciate some help or guidance.
import React, { createElement, useState, useEffect } from 'react';
import { Text, StyleSheet, View, TouchableOpacity, Image } from 'react-native';
import axios from 'axios';
const HomeScreen = ({ navigation }) => {
axios.get("http://100.103.16.113:8081/api/checklists", {
}).then
(function (response) {
console.log(response.data);
}).catch(error => {
console.log(error);
})
const checklists = [{
"id": 1,
"checklisT_DESCRIPTION": "CHECKLIST 1"
},
{
"id": 2,
"checklisT_DESCRIPTION": "CHECKLIST 2"
},
{
"id": 3,
"checklisT_DESCRIPTION": "CHECKLIST 3"
}
]
return (
<View >
<Text style={styles.text}> Select an Audit</Text>
<View style={styles.maincontainer}>
<View style={styles.container}>
{}
{checklists.map(r => (
<TouchableOpacity onPress={() => navigation.navigate('AuditS')} style={styles.button}
>
<Image source={require('../assets/icons8-audit-80.png')} style={styles.Image}></Image>
<Text style={styles.ButtonText}>{r.checklisT_DESCRIPTION}</Text>
</TouchableOpacity >
))}
</View>
</View>
<View style={styles.bottomcontainer}>
<TouchableOpacity onPress={() => navigation.navigate('Login')}
>
<Text style={styles.logout}>LOGOUT</Text>
</TouchableOpacity>
</View>
</View>
);
};
const styles = StyleSheet.create({
text: {
fontSize: 50,
fontFamily: 'Comfortaa-Regular',
alignItems: "center",
textAlignVertical: "center",
textAlign: "center",
justifyContent: "center",
},
container: {
marginTop: 50,
flexDirection: "row",
marginLeft: 50,
width: '100%'
},
maincontainer: {
flexDirection: "column",
width: '80%',
alignContent: "center",
justifyContent: "center",
},
bottomcontainer: {
marginTop: '70%',
width: '100%',
alignItems: "center",
justifyContent: "flex-end",
alignContent: "flex-end",
},
logout: {
marginTop: 50,
margin: 15,
height: 60,
width: 440,
borderColor: '#000000',
backgroundColor: '#000000',
borderWidth: 2,
borderRadius: 10,
fontSize: 18,
textAlign: "center",
textAlignVertical: "center",
color: "#FFFFFF",
fontFamily: 'Comfortaa-Bold'
},
button: {
backgroundColor: '#0f99f5',
fontSize: 16,
color: '#FFF',
width: 150,
height: 150,
borderRadius: 10,
textAlignVertical: "bottom",
textAlign: "center",
marginVertical: 20,
marginHorizontal: 10,
fontFamily: 'Comfortaa-Bold'
},
ButtonText: {
textAlignVertical: "bottom",
textAlign: "center",
fontSize: 16,
color: '#FFF',
marginHorizontal: 10,
fontFamily: 'Comfortaa-Bold'
},
Image: {
width: "50%",
height: "50%",
alignContent: "center",
alignSelf: "center",
marginTop: 10,
marginBottom: 10
}
});
export default HomeScreen;
You need to use a state inside the component.
import React, { createElement, useState, useEffect } from 'react';
const HomeScreen = ({ navigation }) => {
const [checkList, setCheckList] = useState([{
"id": 1,
"checklisT_DESCRIPTION": "CHECKLIST 1"
},
{
"id": 2,
"checklisT_DESCRIPTION": "CHECKLIST 2"
},
{
"id": 3,
"checklisT_DESCRIPTION": "CHECKLIST 3"
}
]);
useEffect(() => {
axios.get("http://100.103.16.113:8081/api/checklists", {
}).then
(function (response) {
setCheckList(response.data); // update the state
}).catch(error => {
console.log(error);
})
}, [])
return (
You simply need to save the callback in a state, something like:
...
const [checklist, setChecklist] = React.useState([]);
useEffect(() => {
axios.get("http://100.103.16.113:8081/api/checklists", {})
.then
(function (response) {
setChecklist(response?.data);
console.log(response.data);
}).catch(error => {
console.log(error);
})
}, []);
...
To avoid null pointer exceptions, I suggest you use optional chaining and block rendering until the promise has been resolved.
You can create a state variable for checklists then populate it using axios.get inside an useEffect. Make sure you verify if the checklist is populated or not by checking checklists.length before mapping over the list and accessing the data to render items.
const HomeScreen = ({ navigation }) => {
// initialize the state variable
const [checklists, setChecklists] = useState([]);
// populate the data
useEffect(() => {
axios.get("http://100.103.16.113:8081/api/checklists")
.then(function (response) {
setChecklists(response.data)
})
.catch(error => {
console.log(error);
})
}, [])
// when mapping over the checklists make sure you check for the checklists.length before mapping
{checklists.length && checklists.map(r =>(
<TouchableOpacity onPress = {() => navigation.navigate('AuditS')}
style={styles.button}
>
<Image source={require('../assets/icons8-audit-80.png')}
style={styles.Image}>
</Image>
<Text style={styles.ButtonText}>{r.checklisT_DESCRIPTION}</Text>
</TouchableOpacity >
))}
}
Here is an example codesandbox
I have an issue with createMaterialTopTabNavigator,
I'm already declaring an AppContainer in my Route.js File,
the error goes away if create a separate AppContainer for a TobTab in a screen I want to add these Tob Tabs in
like this
const Root = createAppContainer(NavTabs);
so I made a specific file contained a Tabs "NavTabs.js"
import { createMaterialTopTabNavigator } from "react-navigation";
import AboutScreen from "./About";
import GalaryScreen from "./Galary";
import ReviewsScreen from "./Reviews";
const NavTabs = createMaterialTopTabNavigator(
{
About: { screen: AboutScreen },
Galaty: { screen: GalaryScreen },
Reviews: { screen: ReviewsScreen }
},
{
tabBarOptions: {
activeTintColor: "#fff",
inactiveTintColor: "#ddd",
tabStyle: {
justifyContent: "center"
},
indicatorStyle: {
backgroundColor: "#fcc11e"
},
style: {
backgroundColor: "#347ed8"
}
}
}
);
export default NavTabs;
and in the File navigations "Route.js" I put it in the StackNavigator like this
and here the full File
const HomeStack = createStackNavigator({
Home: {
screen: Home,
navigationOptions: ({ navigation }) => ({
title: "Home",
headerLeft: <NavigationDrawerStructure navigationProps={navigation} />,
headerRight: (
<TouchableOpacity
onPress={() => navigation.navigate("Notifications")}
style={{ margin: 10 }}
>
<Icon name="ios-notifications" size={28} color="#1DA1F2" />
</TouchableOpacity>
),
headerStyle: {
backgroundColor: "#fff",
shadowOpacity: 0,
elevation: 1,
marginBottom: 20
},
headerTintColor: "#14171a",
headerTitleStyle: {
flex: 1,
fontSize: 25,
justifyContent: "center"
}
})
},
MapScreen: {
screen: MapScreen,
navigationOptions: {
title: "Map",
headerRight: <View />,
// headerLeft: <View />,
headerStyle: {
backgroundColor: "#fff",
shadowOpacity: 0,
elevation: 1,
marginBottom: 0
},
headerTintColor: "#14171a",
headerTitleStyle: {
flex: 1,
fontSize: 25,
justifyContent: "center"
}
}
},
ProviderProfile: {
screen: ProviderProfile,
navigationOptions: {
headerRight: <View />,
// headerLeft: <View />,
headerStyle: {
backgroundColor: "#fff",
shadowOpacity: 0,
elevation: 1
},
headerTintColor: "#14171a",
headerTitleStyle: {
flex: 1,
fontSize: 25,
justifyContent: "center"
}
}
},
Order: {
screen: Order,
navigationOptions: {
title: "Order",
headerRight: <View />,
// headerLeft: <View />,
headerTintColor: "#fff",
headerStyle: {
backgroundColor: "#fff",
shadowOpacity: 0,
elevation: 1
},
headerTintColor: "#14171a",
headerTitleStyle: {
flex: 1,
fontSize: 25,
justifyContent: "center"
}
}
},
Tabs: NavTabs
});
and when I Import it in my screen " profile"
like this
<View>
<View style={{ flexDirection: "row", marginTop: 10 }}>
<TouchableOpacity
style={{
backgroundColor: "#1567d3",
width: 130,
borderRadius: 100,
justifyContent: "center",
marginRight: 50,
height: 40
}}
onPress={() => alert("Message")}
>
<Text
style={{
textAlign: "center",
color: "#fff",
fontSize: 18,
fontWeight: "300"
}}
>
Message
</Text>
</TouchableOpacity>
<TouchableOpacity
style={{
backgroundColor: "#1567d3",
width: 130,
borderRadius: 100,
justifyContent: "center",
height: 40
}}
onPress={() =>
this.props.navigation.navigate("Order", {
providerName,
providerId,
providerService,
gKey,
token,
region
})
}
>
<Text
style={{
textAlign: "center",
color: "#fff",
fontSize: 18,
fontWeight: "300"
}}
>
Send Order
</Text>
</TouchableOpacity>
</View>
<NavTabs />
</View>
I got the error like above, so how to handle this without making the other app container?
cuz when i navigate from Map screen to Profile screen i pass some Params and i want to use these params in the Tabs
this.props.navigation.navigate('ProviderProfile', {
providerId: marker.id,
providerName: marker.name,
providerService: marker.service,
gKey: marker.gKey,
token: marker.token._55,
region: region
})
the result should be like this " as you see i have a name "Loy" i wanna use it in About Tab"
I'm trying to initialize a Text component in a parent component with a certain state, but it's not showing up at all. This should be something really simple and something I've done multiple times before, what am I doing wrong here? Nothing is showing up in the text component. Here is the component code:
import React from 'react';
import { View, Text, TextInput, StyleSheet } from 'react-native';
export class GeneralInput extends React.Component {
constructor(props) {
super(props);
this.state = {
placeholder: this.props.placeholder,
inputValue: "",
inputting: false,
validationMessage: "This is a required field",
validationStyles: styles.noValidation,
};
}
whenInputIsFocused() {
this.setState({placeholder: ""});
}
whenInputIsBlurred() {
this.setState({validationMessage: "This field is required"});
/* if (this.state.inputValue === "") {
this.setState({placeholder: this.props.placeholder});
}*/
}
storeValue = (inputValue) => {
this.setState({inputValue});
this.props.onChange({key: this.props.fieldId, value: inputValue});
}
focusNextField(nextField) { this.refs[nextField].focus(); }
render() {
const autoFocus = this.props.autoFocus == 'true';
const multiline = this.props.multiline == 'true';
return(
<View style={styles.outerContainer}>
<Text style={styles.labelText}>{this.props.labelText}</Text>
<View style={styles.inputContainer}>
<TextInput
autoCapitalize='none'
autoFocus={this.props.autoFocus}
onChangeText={this.storeValue}
value={this.state.inputValue}
secureTextEntry={this.props.secureTextEntry}
onBlur={this.whenInputIsBlurred.bind(this)}
onFocus={this.whenInputIsFocused.bind(this)}
underlineColorAndroid="transparent"
keyboardType={this.props.type}
returnKeyType={this.props.returnKeyType}
placeholder={this.state.placeholder}
placeholderTextColor='rgba(255, 255, 255, 0.3)'
multiline={multiline}
selectTextOnFocus={false}
onSubmitEditing={() => {this.focusNextField(this.props.ref)}}
blurOnSubmit={(this.props.moveAlongType === 'next') ? false : true}
style={styles.inputStyles} />
<Text style={styles.validationText}>{this.state.validationMessage}</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
outerContainer: {
justifyContent: 'center',
alignItems: 'flex-start',
width: '90%',
marginBottom: 20,
},
labelText: {
fontFamily: 'rubik-bold',
fontSize: 14,
fontWeight: 'bold',
color: '#fff',
marginBottom: 5,
},
inputContainer: {
height: 40,
width: '100%',
backgroundColor: 'rgba(255, 255, 255, 0.3);',
shadowColor: 'rgba(0, 0, 0, 0.15)',
shadowOffset: {width: 0,height: 2},
shadowOpacity: 0,
shadowRadius: 0,
borderRadius: 2,
},
inputStyles: {
height: '100%',
width: '100%',
fontSize: 14,
color: '#fff',
paddingLeft: 15,
fontFamily: 'rubik-bold',
},
validationText: {
color: '#e16e17',
fontSize: 12,
fontFamily: 'rubik-bold',
marginTop: 3,
display: 'none',
},
});
Assuming you mean this
<Text style={styles.validationText}>{this.state.validationMessage}</Text>
Your styles have
validationText: {
color: '#e16e17',
fontSize: 12,
fontFamily: 'rubik-bold',
marginTop: 3,
display: 'none',
},
The display:'none' is going to make it not show up
I tried your code and modified the backgroundColor for the text area.
labelText: {
backgroundColor: "red",
...
I get this, which I believe is what you are looking for:
Are you showing the text on a white background?
I am using react native to build an app and the only problem i am having is that i have a progress bar that keeps track of the users progress but when I close the app completely and open it back up everything resets to its original data. How do I make it so it will keep the data when they close the app?
Not sure how to add in the AsyncStorage
Here is my code:
'use strict';
var React = require('react-native');
var ProgressBar = require('react-native-progress-bar');
var {
AppRegistry,
AsyncStorage,
StyleSheet,
Text,
View,
TouchableHighlight
} = React;
var PROGRESS = 0;
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#FFF',
},
button: {
alignSelf: 'center',
marginTop: 50,
width: 100,
height: 50,
backgroundColor: '#0059FF',
borderRadius: 8,
borderWidth: 2,
borderColor: '#0059FF'
},
buttonClear: {
alignSelf: 'center',
marginTop: 10,
width: 100,
height: 50,
backgroundColor: '#3B3A3A',
borderRadius: 8,
borderWidth: 2,
borderColor: '#3B3A3A'
},
buttonText: {
fontSize: 18,
textAlign: 'center',
lineHeight: 33,
color: '#FFF',
}
});
class BasicStorageExample extends React.Component {
constructor(props) {
super(props);
this.state = {
progress: PROGRESS
};
}
onButtonPress() {
this.setState({
progress: PROGRESS += 0.2
});
}
onButtonClearPress() {
PROGRESS = 0;
this.setState({
progress: 0
});
}
render() {
return (
<View style={styles.container}>
<ProgressBar
fillStyle={{}}
backgroundStyle={{backgroundColor: '#cccccc', borderRadius: 2}}
style={{marginTop: 10, width: 300}}
progress={this.state.progress} />
<TouchableHighlight
style={styles.button}
underlayColor='#002C7F'
onPress={this.onButtonPress.bind(this)}>
<Text style={styles.buttonText}>Done</Text>
</TouchableHighlight>
<TouchableHighlight
style={styles.buttonClear}
underlayColor='#002C7F'
onPress={this.onButtonClearPress.bind(this)}>
<Text style={styles.buttonText}>Clear</Text>
</TouchableHighlight>
</View>
);
}
};
AppRegistry.registerComponent('BasicStorageExample', () => BasicStorageExample);
you can try taking a look at this article by Nic Raboy. It has a video demonstration as well as example code.
https://blog.nraboy.com/2015/09/saving-data-in-your-react-native-mobile-application/
Here is some example code (from the article) that demonstrates saving your data with async storage. Cheers!
"use strict";
var React = require("react-native");
var {
AppRegistry,
StyleSheet,
Text,
View,
TextInput,
AsyncStorage,
} = React;
var ReactProject = React.createClass({
componentDidMount: function() {
AsyncStorage.getItem("myKey").then((value) => {
this.setState({"myKey": value});
}).done();
},
getInitialState: function() {
return { };
},
render: function() {
return (
<View style={styles.container}>
<Text style={styles.saved}>
{this.state.myKey}
</Text>
<View>
<TextInput
style={styles.formInput}
onChangeText={(text) => this.saveData(text)}
value="" />
</View>
<Text style={styles.instructions}>
Type something into the text box. It will be saved to
device storage. Next time you open the application, the saved data
will still exist.
</Text>
</View>
);
},
saveData: function(value) {
AsyncStorage.setItem("myKey", value);
this.setState({"myKey": value});
}
});
var styles = StyleSheet.create({
container: {
padding: 30,
flex: 1,
justifyContent: "center",
alignItems: "stretch",
backgroundColor: "#F5FCFF",
},
formInput: {
flex: 1,
height: 26,
fontSize: 13,
borderWidth: 1,
borderColor: "#555555",
},
saved: {
fontSize: 20,
textAlign: "center",
margin: 10,
},
instructions: {
textAlign: "center",
color: "#333333",
marginBottom: 5,
marginTop: 5,
},
});
AppRegistry.registerComponent('ReactProject', () => ReactProject);