How to refactoring react components with member variable to es6 classes - react-native

How can I refactor React components with a member variable to es6 classes
It works without state variable. Why, when running the code below, do I get a big red screen with "Can't add property counter, object is not extensible"?
'use strict';
let Dimensions = require('Dimensions');
let totalWidth = Dimensions.get('window').width;
let leftStartPoint = totalWidth * 0.1;
let componentWidth = totalWidth * 0.8;
import React, {
AppRegistry,
Component,
StyleSheet,
Text,
TextInput,
View
} from 'react-native';
class Login extends Component {
constructor(props) {
super(props);
this.counter =23;
this.state = {
inputedNum: ''
};
}
updateNum(aEvent) {
this.setState((state) => {
return {
inputedNum: aEvent.nativeEvent.text,
};
});
}
buttonPressed() {
this.counter++;
console.log(':::'+this.counter);
}
render() {
return (
<View style={styles.container}>
<TextInput style={styles.numberInputStyle}
placeholder={'input phone number'}
onChange={(event) => this.updateNum(event)}/>
<Text style={styles.bigTextPrompt}
onPress={this.buttonPressed}>
Press me...
</Text>
</View>
);
}
}
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
},
numberInputStyle: {
top: 20,
left: leftStartPoint,
width: componentWidth,
backgroundColor: 'gray',
fontSize: 20
},
bigTextPrompt: {
top: 70,
left: leftStartPoint,
width: componentWidth,
backgroundColor: 'gray',
color: 'white',
textAlign: 'center',
fontSize: 60
}
});
AppRegistry.registerComponent('Project18', () => Login);

You need to set up the value in the constructor:
constructor(props) {
super(props)
this.counter = 23
}
You may be receiving the errors because of the way the state is being set. Try setting the state like this:
updateNum(aEvent) {
this.setState({
inputedNum: aEvent.nativeEvent.text,
})
}
And the onPress function should be called like this:
<Text style={styles.bigTextPrompt} onPress={() => this.buttonPressed()}>
I've set up a full working project here also pasted the code below.
https://rnplay.org/apps/Se8X5A
'use strict';
import React, {
AppRegistry,
Component,
StyleSheet,
Text,
TextInput,
View,
Dimensions
} from 'react-native';
let totalWidth = Dimensions.get('window').width;
let leftStartPoint = totalWidth * 0.1;
let componentWidth = totalWidth * 0.8;
class SampleApp extends Component {
constructor(props) {
super(props);
this.counter =23;
this.state = {
inputedNum: ''
};
}
updateNum(aEvent) {
this.setState({
inputedNum: aEvent.nativeEvent.text,
})
}
buttonPressed() {
this.counter++;
console.log(':::'+this.counter);
}
render() {
return (
<View style={styles.container}>
<TextInput style={styles.numberInputStyle}
placeholder={'input phone number'}
onChange={(event) => this.updateNum(event)}/>
<Text style={styles.bigTextPrompt}
onPress={() => this.buttonPressed()}>
Press me...
</Text>
</View>
);
}
}
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
},
numberInputStyle: {
top: 20,
left: leftStartPoint,
width: componentWidth,
backgroundColor: 'gray',
fontSize: 20,
width:200,
height:50
},
bigTextPrompt: {
top: 70,
left: leftStartPoint,
width: componentWidth,
backgroundColor: 'gray',
color: 'white',
textAlign: 'center',
fontSize: 60
}
});
AppRegistry.registerComponent('SampleApp', () => SampleApp);

Related

How view saved data by AsyncStorage?

I have a code that saves and reads the value of a state through AsyncStorage, however when closing the app or changing the screen the value returns to the original state value, which in my case is zero. How do I change the screen or close the app so the value remains the last changed? What alternative to state variables?
My code is:
import React, { Component } from 'react'
import { Text, View, AsyncStorage, TextInput, StyleSheet, TouchableOpacity } from 'react-native'
export default class App extends Component {
constructor(props){
super(props);
this.state = {
txtInputData: '',
getValue: '',
}
}
saveValue = () => {
if(this.state.txtInputData){
AsyncStorage.setItem('key_default', this.state.txtInputData)
this.setState({txtInputData: ''})
alert('Data salved!')
}else{
alert('Please, fill the data!')
}
}
getValue = () => {
AsyncStorage.getItem('key_default').then(value => this.setState({getValue: value}))
}
render() {
return (
<View style={styles.mainContainer}>
<Text>Using AsyncStorage</Text>
<TextInput
style={styles.textInput}
placeholder = 'type here'
value = {this.state.txtInputData}
onChangeText={data => this.setState({txtInputData: data})}
/>
<TouchableOpacity
onPress={this.saveValue}
style={styles.TouchableOpacity}
>
<Text>Save value</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={this.getValue}
style={styles.TouchableOpacity}
>
<Text> Read value</Text>
</TouchableOpacity>
<Text>Value read:{this.state.getValue}</Text>
</View>
)
}
}
const styles = StyleSheet.create({
mainContainer: {
flex: 1,
padding: 20,
},
textInput: {
marginTop: 10,
borderWidth: 1,
borderColor: '#fa19',
fontSize: 15
},
TouchableOpacity: {
width: '50%',
marginTop: 10,
borderWidth: 1,
borderColor: '#fa19',
padding: 10,
alignSelf: 'center',
alignItems: 'center'
}
})
Just setStat of txtInputData instead of getValue like this
getValue = () => {
AsyncStorage.getItem('key_default').then(value => this.setState({txtInputData: value}))
}

React native SectionList not updating

I am developing a sample app as part of learning react-native, in which it has a ColorForm that accepts the value from a TextInput and with the help of Props, the data will be sent to the Main view, such as App. The App has a SectionList that doesn't update with the new value inputs from ColorForm.
Following is the source code that I have used:
App.js
import React, { Component } from 'react'
import {
StyleSheet,
SectionList,
Text,
Alert
} from 'react-native'
import ColorButton from './components/ColorButton'
import ColorForm from './components/ColorForm'
class App extends Component {
constructor() {
super()
this.state = {
backgroundColor: 'blue',
availableColors: ['red', 'green', 'yellow', 'pink']
}
this.changeColor = this.changeColor.bind(this)
this.newColor = this.newColor.bind(this)
}
changeColor(backgroundColor) {
this.setState({ backgroundColor })
}
newColor(color) {
const colors = [
...this.state.availableColors,
color
]
this.setState(colors)
}
render() {
const { backgroundColor, availableColors } = this.state
return (
<SectionList style={styles.list}
backgroundColor={backgroundColor}
sections={[{ title: "Header", data: availableColors }]}
renderSectionHeader={({ section }) => (
<ColorForm onNewColor={this.newColor} />
)}
renderItem={({ item }) => (
<ColorButton backgroundColor={item} onSelect={this.changeColor} />
)}
keyExtractor={(item, index) => index}
/>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 20
},
list: {
marginTop: 40
}
})
export default App
ColorForm.js
import React, { Component } from 'react'
import {
View,
Text,
StyleSheet,
TextInput
} from 'react-native'
import PropTypes from 'prop-types'
export default class ColorForm extends Component {
constructor() {
super()
this.state = {
txtColor: ''
}
this.submit = this.submit.bind(this)
}
submit() {
this.props.onNewColor(this.state.txtColor.toLowerCase())
this.setState({ txtColor: '' })
}
render() {
return (
<View style={styles.container}>
<TextInput
style={styles.txtInput}
placeholder="Enter a color..."
onChangeText={(txtColor) => this.setState({ txtColor })}
value={this.state.txtColor}
/>
<Text style={styles.button} onPress={this.submit}>Add</Text>
</View>
)
}
}
ColorForm.propTypes = {
onNewColor: PropTypes.func.isRequired
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-around',
backgroundColor: 'lightgrey',
height: 70,
paddingTop: 20
},
txtInput: {
flex: 1,
margin: 5,
padding: 5,
borderWidth: 2,
fontSize: 20,
borderRadius: 5,
backgroundColor: 'snow'
},
button: {
backgroundColor: 'darkblue',
margin: 5,
padding: 5,
alignItems: 'center',
justifyContent: 'center',
color: 'white',
fontSize: 20
}
})
Can anyone help me to sort out the issue? Thanks in advance.
It looks like the state is not being updated in your method newColor, since availableColors is an array u can use push operation to add new value to the array update the code as below and it will work.
newColor(color) {
console.log('adding', color)
const colors = this.state.availableColors
colors.push(color)
this.setState(colors)
}

How to implement swiping to access different navigation screens in React Native?

I am trying to build an interface similar to the Snapchat's interface where you can swipe left/right/up to access different screen/navigator. Currently I am using the DrawerNavigator but it's kind of janky because I am using a DrawerNavigator on top of another DrawerNavigator.
Does anyone have a good suggestion on the best way to do this?
Thanks!
The following code is implementing easy 4-way swipe navigation across views declaratively in under 20 lines, no Javascript!
import Swiper from 'react-native-swiper'
import randomcolor from 'randomcolor'
const {
View,
Text,
StyleSheet
} = React
var styles = StyleSheet.create({
container: {
flex: 1
},
view: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}
})
class TitleText extends React.Component {
render() {
return (
<Text style={{ fontSize: 48, color: 'white' }}>
{this.props.label}
</Text>
)
}
}
class Home extends React.Component {
viewStyle() {
return {
flex: 1,
backgroundColor: randomcolor(),
justifyContent: 'center',
alignItems: 'center',
}
}
render() {
return (
<Swiper
loop={false}
showsPagination={false}
index={1}>
<View style={this.viewStyle()}>
<TitleText label="Left" />
</View>
<Swiper
horizontal={false}
loop={false}
showsPagination={false}
index={1}>
<View style={this.viewStyle()}>
<TitleText label="Top" />
</View>
<View style={this.viewStyle()}>
<TitleText label="Home" />
</View>
<View style={this.viewStyle()}>
<TitleText label="Bottom" />
</View>
</Swiper>
<View style={this.viewStyle()}>
<TitleText label="Right" />
</View>
</Swiper>
)
}
}
export default Home
Unfortunately, vertical navigation is not supported on Android yet.
I’ve used the react-native-swiper component in a previous project and loved it! I figured I can tweak it a little bit to meet my requirements.
You can clearly see that I have seperated my screens and navigation files in a separate folder.
This is my root navigator file:
import {
createStackNavigator
} from 'react-navigation';
import Login from '../screens/Login';
import SplashScreen from '../screens/SplashScreen';
import HomeNavigation from './HomeNavigation';
export default RootNavigation = createStackNavigator({
// Settings:UserProfile,
SplashScreen: SplashScreen,
Login: Login,
DrawerNavigation: HomeNavigation
}, {
headerMode: 'none',
});
This is my root navigator file:
Here i declare all my screens and link it to the root navigator
import React, {
Component
} from 'react';
import {
Text,
View,
Image,
SafeAreaView,
ScrollView,
Dimensions,
AsyncStorage,
ImageBackground,
TouchableOpacity,
Platform
} from 'react-native';
import {
Icon
} from 'native-base';
import {
createStackNavigator,
createDrawerNavigator,
DrawerItems,
createSwitchNavigator,
Header
} from 'react-navigation';
import AppDataStorage from '../helper/AppDataStorage';
import Colors from '../config/Colors';
import {
RNToasty
} from 'react-native-toasty';
import Home from '../screens/Home';
import Contact from '../screens/Contact';
import AboutUs from '../screens/AboutUs';
import Search from '../screens/Search';
import MyProfile from '../screens/MyProfile';
import {
getStatusBarHeight
} from 'react-native-status-bar-height';
var width = Dimensions.get('window').width;
var height = Dimensions.get('window').height;
var drawerWidth = ((width * 0.75) > 350) ? 350 : (width * 0.75);
const ImageHeader = props => ( <
View style = {
{
backgroundColor: '#eee'
}
} >
<
LinearGradien style = {
{
height: '100%',
width: '100%'
}
}
start = {
{
x: 0,
y: 1
}
}
end = {
{
x: 1,
y: 0
}
}
colors = {
['#4c669f', '#3b5998', '#192f6a']
}
/> <
Header { ...props
}
style = {
{
backgroundColor: 'transparent'
}
}
/> < /
View >
);
const headerOptions = (props) => {
return {
// header: (props) => <ImageHeader {...props} />,
headerStyle: {
backgroundColor: Colors.transparent,
paddingTop: Platform.OS === 'ios' ? 0 : getStatusBarHeight(),
height: Header.HEIGHT + (Platform.OS === 'ios' ? 0 : getStatusBarHeight()),
},
headerTintColor: Colors.white,
headerTitleStyle: {
fontWeight: 'bold',
},
headerMode: 'float',
headerLeft: < Icon
onPress = {
() => props.navigation.openDrawer()
}
name = "menu"
type = 'MaterialIcons'
style = {
{
color: 'white',
marginLeft: 10
}
}
/>,
}
};
class homeDrawerComponent extends Component {
constructor(props) {
super(props);
this.state = {
user: null
};
}
async componentDidMount() {
let user = await AppDataStorage.getUser();
console.log("user drawer", user);
await this.setState({
user: user
});
}
render() {
const email = this.state.user ? this.state.user.email : '';
const name = this.state.user ? (this.state.user.firstName + ' ' + this.state.user.lastName) : '';
return ( <
View style = {
{
flex: 1
}
} >
<
ImageBackground resizeMode = 'cover'
source = {
require('../assets/images/Cover.png')
}
style = {
{
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'center',
height: 200,
marginBottom: 32
}
} >
<
View style = {
{
width: 80,
height: 80,
backgroundColor: Colors.white,
marginTop: 40,
borderRadius: 40
}
} >
<
Image source = {
require('../assets/images/drawer-logo.png')
}
style = {
{
width: 80,
height: 80,
}
}
resizeMode = 'contain' / >
<
/View> <
Text style = {
{
marginTop: 10,
color: Colors.white,
fontSize: 14,
}
} > {
name
} <
/Text> <
Text style = {
{
color: Colors.white,
fontSize: 14,
}
} > {
email
} <
/Text> < /
ImageBackground > <
ScrollView showsVerticalScrollIndicator = {
false
} >
<
DrawerItems activeBackgroundColor = '#1a9eae1a'
activeTintColor = {
Colors.secondaryColor
}
inactiveTintColor = {
Colors.primaryColor
}
labelStyle = {
{
color: Colors.text2
}
} { ...this.props
}
/> <
TouchableOpacity onPress = {
() => {
AsyncStorage.clear();
OneSignal.setSubscription(false);
RNToasty.Info({
title: 'You have been logged out.'
})
this.props.navigation.navigate('SplashScreen');
}
} >
<
View style = {
{
padding: 16,
flexDirection: 'row',
alignItems: 'center'
}
} >
<
Icon
type = "MaterialCommunityIcons"
name = "logout"
style = {
{
fontSize: 24,
color: Colors.primaryColor,
fontWeight: 'bold'
}
}
/> <
Text style = {
{
fontSize: 14,
color: Colors.text2,
fontWeight: 'bold',
marginLeft: 32
}
} > Sign Out < /Text> < /
View > <
/TouchableOpacity> < /
ScrollView > {
/* <TouchableOpacity onPress={() => {
AsyncStorage.clear();
RNToasty.Info({ title: 'You have been logged out.' })
this.props.navigation.navigate('SplashScreen');
}}> */
} {
/* <Icon
onPress={() => {
AsyncStorage.clear();
OneSignal.setSubscription(false);
RNToasty.Info({ title: 'You have been logged out.' })
this.props.navigation.navigate('SplashScreen');
}}
type="MaterialCommunityIcons"
name="logout"
style={{ color: Colors.secondaryColor, padding: 16, textAlign: 'left', marginBottom: 20, fontWeight: 'bold' }}> Logout</Icon> */
} <
/View>
)
}
}
const HomeStack = createStackNavigator({
Home: Home,
Search: Search,
Contact: Contact,
}, {
defaultNavigationOptions: headerOptions
});
HomeStack.navigationOptions = ({
navigation
}) => {
let drawerLockMode = 'unlocked';
if (navigation.state.index > 2) {
drawerLockMode = 'locked-closed';
}
return {
drawerLockMode,
};
};
const AboutUsStack = createStackNavigator({
AboutUs: AboutUs,
}, {
defaultNavigationOptions: headerOptions
});
export default HomeNavigation = createDrawerNavigator({
Home: {
screen: HomeStack,
navigationOptions: {
drawerLabel: 'Home',
drawerIcon: ({
tintColor
}) => ( <
Icon type = "FontAwesome5"
name = "home"
style = {
{
fontSize: 20,
color: tintColor
}
}
/>
)
}
},
{
header: null,
contentComponent: homeDrawerComponent,
// drawerWidth
},
);
You're good to go!
Hope this helps.

Created a custom button component but I can't get it to appear disabled

I am creating a custom button on react native and trying to have it appear as disabled (by lowering the opacity) if the credentials are bad or upon loading.
I have the component working correctly but it won't lower the opacity
I have played around with the values but nothing seems to take, I'm new to this so maybe I'm missing something obvious.
This is my button
import React, { Component } from 'react';
import { StyleSheet, Text, TouchableOpacity } from "react-native";
import colors from "../config/colors";
export default class Button extends React.Component {
constructor(props){
super(props);
this.state = {
label: "",
disabled: true
}
}
render (){
const { disabled, label, onPress } = this.props;
const containerStyle = [
styles.container,
disabled ? styles.containerDisabled : styles.containerEnabled
];
return (
<TouchableOpacity
style={styles.container}
onPress={onPress}
disabled={disabled}
>
<Text style={styles.text}>{label}</Text>
</TouchableOpacity>
);
}
}
const styles = StyleSheet.create({
container: {
width: "100%",
alignItems: "center",
justifyContent: "center",
backgroundColor: colors.BLUE,
marginBottom: 12,
paddingVertical: 12,
borderRadius: 4,
borderWidth: StyleSheet.hairlineWidth,
borderColor: "rgba(255, 255, 255, 0.7)",
},
containerEnabled: {
opacity: 1
},
containerDisabled: {
opacity: 0.3
},
text: {
color: colors.WHITE,
textAlign: "center",
height: 20
}
});
It appears with opacity:1 even though I meant for it to be 0.3 from the beginning.
On my app.js I call it by doing
constructor(props){
super(props);
this.state = {
email: "",
password: "",
emailTouched: false,
passwordTouched: false
}
...
render() {
const {
email,
password,
emailTouched,
passwordTouched
} = this.state;
...
<Button
label={strings.LOGIN}
onPress={this.handleLoginPress}
disabled={!email || !password}
/>
In your render method - you don't have any prop of disabled, rather use const {disabled} = this.state. that should work

How to pass a variable on the transform property style in react-native?

I try to pass a variable on the transform property style in react-native but it don't work. My code bellow :
import React, { Component } from 'react';
import { AppRegistry, StyleSheet, Text, View } from 'react-native';
import { Accelerometer, Gyroscope } from 'react-native-sensors';
import { sensors } from 'react-native-sensors';
export default class Sensors extends Component {
constructor(props) {
super(props);
this.state = {
rotate: 0
}
}
render() {
var degree = this.state.rotate;
return (
<View style={styles.container}>
<View style={styles.fleche}></View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
fleche: {
width: 5,
height: 150,
backgroundColor: '#000000',
borderRadius: 5,
transform: [{ rotate: '' + this.state.rotate + 'deg' }],
}
});
AppRegistry.registerComponent('Compass', () => Sensors);
I don't know the way to pass the variable in the transform style. Currently, I have this error : undefine is not an object(evaluating 'this.state.rotate').
Try this:
render(){
const transform = [{ rotate: this.state.rotate + 'deg' }]
var degree = this.state.rotate
return (
<View style={styles.container}>
<View style={[styles.fleche, transform]} />
</View>
)
}