React native, "this" keyword is undefied - javascript

so I wanted to use this.props.navigation.navigate() and I got an error message saying undefined.
after reading here in stockOverflow I saw that I needed declare a constructor like this
constructor(props) {
super(props);
}
however this keeps giving me an error saying ";" is was expected regardless of what I do, here is a simplified version of my code
const activityStyles = ActivitiesStyles.createStyles()
export default (props) => {
const {item: event, sensorID, homeInfo} = props
return (
<View style={activityStyles.linkContent} underlayColor={Colors.navigationBkgdActive}>
<View style={{flex: 0.60, flexDirection: 'row'}}>
<TouchableHighlight onPress={(event)=>{this.props.navigation.navigate("WalkThru")}}>
<SensorIcon style={iconStyle} size={Typography.bodyLineHeight} type={event.type} />
</TouchableHighlight>
<TextInput
placeholder={event.type}
autoCapitalize={true}
style={activityStyles.text}>
</TextInput>
</View>
</View>
)
}

As Emile Bergeron suggested, you should go with props since this keyword is available only for Class-Based components.
A class based component would be as follows.
export default class componentName extends Component {
constructor(props) {
super(props)
this.state = {
}
}
render() {
return (
<TouchableHighlight
<View style={activityStyles.linkContent} underlayColor={Colors.navigationBkgdActive}>
<TouchableHighlight onPress={(event)=>{this.props.navigation.navigate("WalkThru")}}>
<SensorIcon style={iconStyle} size={Typography.bodyLineHeight} type={event.type} />
</TouchableHighlight>
<TextInput
placeholder={event.type}
</TextInput>
</View>
</TouchableHighlight>
)
}
}
Furthermore, I can propose you look into differences between Stateless Functional Components and Class Components in React / React-Native.

Related

Natigate to different screes within same page in React Native

I have made a main screen in which I have added three button in the header, on pressing I want to open three different screens respectively but its not working.
Here's what I've tried:
constructor(props) {
super(props);
this.state = {
initialstate: 0, //Setting initial state for screens
};
}
render(){
return(
<View style={styles.container}>
<TouchableOpacity onPress={() => this.setState({ initialstate: 0})}>
<Image source={require('../../assets/add.png')}
resizeMode="contain"/>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.setState({ cardstate: 1})}>
<Image source={require('../../assets/request.png')}
resizeMode="contain"/>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.setState({ cardstate: 2})}>
<Image source={require('../../assets/send.png')}
resizeMode="contain"/>
</TouchableOpacity>
{this.state.initialstate == 0 ? ( <RequestComp/> ) : ( <TopUpComp/> ) } //Over Here when I use the Third Screen like " : <SendComp/> " it gives me JXS error says "EXPECTED }"
</View>
The first problem is that you have an initialState state variable that is only updated by the first buttons and the other two are setting cardState so even if the ternary statement was formatted correctly it wouldn't have worked either way
But aside from this problem I don't recommend using a ternary for what you're trying to do, because the conditions become difficult to read.
There are multiple ways of doing this, but I like the approach of the accepted answer here React render various components based on three logic paths). The idea is to create an object that holds a mapping of strings to components. Then you can conditionally render an item based on the current key value.
Here's an example of how you could refactor your code to use this approach:
const tabComponents = {
request: <RequestComp />,
topUp: <TopUpComp />,
send: <SendComp />,
};
class CustomTabs extends React.Component {
constructor(props) {
super(props);
this.state = {
cardstate: 'request', // Setting initial state for screens
};
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity
onPress={() => this.setState({ cardstate: 'request' })}>
// Button content...
</TouchableOpacity>
<TouchableOpacity onPress={() => this.setState({ cardstate: 'topUp' })}>
// Button content...
</TouchableOpacity>
<TouchableOpacity
onPress={() => this.setState({ cardstate: 'send' })}>
// Button content...
</TouchableOpacity>
{tabComponents[this.state.cardstate]}
</View>
);
}
}

Get value from a TextInput component in react native

Dynamically generate a TextInput when you press a button but I can’t get the value that the user digits,try to use states but I can’t because it’s not with the other general textInputs but it’s imported as Field.
try to create a state in the component file and move it to the general view and print it to see if it works and not...is there any way to bring this state?
general view:
import Campo from './campoInput';
constructor(props){
super(props);
this.state={
Cbusto:"",
Ccintura:"",
Ccadera:"",
valueArray: []
};
this.addNewEle = false;
}
agregarCampo=()=>{
this.addNewEle = true;
const newlyAddedValue = { text: 'prueba'};
this.setState({
valueArray: [...this.state.valueArray, newlyAddedValue]
});
}
render(){
return(
------Here are the normal textInput-----
<View style={{ flex: 1, padding: 4 }}>
{this.state.valueArray.map((ele) => {
return <Campo item={ele} />;
})}
</View>
<View style={styles.flex}>
<View style={styles.ButtonAdd}>
<Button
title="Add input"
color="#B13682"
onPress={this.agregarCampo}
></Button>
</View>
)
}
Component:
constructor(props){
super(props);
this.state={
info:""
};
}
render(){
return(
<View>
<Text>pruba:{this.props.item.text}</Text>
<View style={styles.input}>
<TextInput onChangeText={(text) => this.setState({info:text})}></TextInput>
</View>
</View>
)
}
can be solved by adding the onChangeText event to the Field component in the overview and in the same way in the TextInput of the component being imported, using props status
General view:
<View style={{ flex: 1, padding: 4 }}>
{this.state.valueArray.map((ele) => {
return <Campo item={ele}
onChangeText={(text) => this.setState({ info: text })}
/>;
})}
</View>
Component
<View>
<Text>pruba:{this.props.item.text}</Text>
<View style={styles.input}>
<TextInput onChangeText={this.props.onChangeText}></TextInput>
</View>
</View>

this.setState not changing state when using onChangeText React Native

I've tried a few methods to get setState() to update the value of state. Currently the text in the <TextInput> changes, but the value in this.state doesn't change.
I have the console.log in the right place, I've tried writing external functions, I've messed around with the variable's names but nothing seems to work.
import * as React from 'react';
import { View, Text, TextInput, TouchableHighlight, Dimensions, StyleSheet } from "react-native";
import PropTypes from "prop-types";
class EditNote extends React.Component{
constructor(props){
super(props)
this.state = {
title: '',
text: '',
id: ''
}
}
// TODO: Change textboxes to match the props from the NoteList
static getDerivedStateFromProps(props){
return(
{...props.route.params}
)
}
render(){
return(
<View style={s.container}>
<View style={s.titleContainer}>
<Text style={s.titleText}>Edit Note</Text>
<View style={{flex: 1}}/>
</View>
<View style={s.inputContainer}>
<TextInput
style={{...s.input, ...s.titleInput}}
autoCapitalize='words'
keyboardAppearance='dark'
placeholderTextColor='#DDD'
onChangeText={(title) => { this.setState({title: title}, () => console.log(this.state)) }}
defaultValue={this.state.title}
/>
<TextInput
style={{...s.input, ...s.textInput}}
autoCapitalize='sentences'
keyboardAppearance='dark'
placeholderTextColor='#DDD'
multiline
onChangeText={(text) => { this.setState({text: text}, () => console.log(this.state)) }}
defaultValue={this.state.text}
/>
</View>
<View style={s.buttonContainer}>
<TouchableHighlight
style={s.backButton}
onPress={() => this.props.nav.navigate('NoteListView')}
underlayColor='#300030'
>
<Text style={s.buttonText}>Cancel</Text>
</TouchableHighlight>
<TouchableHighlight
style={s.addButton}
onPress={() => {
console.log(this.state.note)
this.props.nav.navigate('NoteListView', {note: this.state, mode: 'edit'})
}}
underlayColor='#300030'
>
<Text style={s.buttonText}>Edit</Text>
</TouchableHighlight>
</View>
</View>
)
}
}
export default EditNote
I just realized that this is a problem with two parts.
The first problem is that props.route.params is unaffected by subsequent render() calls. This means that even if you re-render the component, the same initial properties are used.
The second is getDerivedStateFromProps(). Every time the render function is called it calls getDerivedStateFromProps() right before it which sets the state to the initial route parameters.
This problem can be fixed by:
Clearing the initial route parameters in the render function after their initial use. Something a little like this at the beginning of the render()function will work. this.props.route.params = undefined
Using an if statement and a variable in state to regulate when the props should update the state.
Refactor the code to make use of the props
Option 3 is how things should be correctly done but the best solution depends on how your code works.

How to send data from one screen to another screen in react native?

I am new to react native how can i send data from one screen to another screen using props in android not for ios my code is as below
Home.js
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
qwerty:{
data:[],
},
};
}
goPressed(navigate){
navigate("Product");
}
render() {
const { navigate } = this.props.navigation;
contents = this.state.qwerty.data.map((item) => {
return (
<View key={item.p1.id}>
<View>
<Text>{item.p1.content}</Text>
</View>
<View>
<TouchableHighlight onPress={() => this.goPressed(navigate)}>
<Text>
Go
</Text>
</TouchableHighlight>
</View>
</View>
);
});
return (
<ScrollView style={styles.container}>
{contents}
</ScrollView>
);
}
}
export default Home;
this is my home.js , I want pass data i.e {item.p1.content} to another screen i.e product.js so how can i do it what modification should i do?
Product.js
export default class Products extends Component {
static navigationOptions = {
title: "Products",
};
render() {
return (
<View style={{ flex: 1 }}>
<Text>{item.p1.content}</Text>
</View>
);
}
}
Send data to other screen
this.props.navigation.navigate('Your Screen Name' , { YourParamsName: "Foo"});
Receive data from other screen
this.props.navigation.state.params.YourParamsName
One method is to simply pass the date you are storing in 'qwerty' as a props to the next scene.
In Home.js you can modify your goPressed method to be something like...
goPressed(navigate){
navigate("Product", {passedData: this.state.qwerty.item.p1.content});
}
Then in Product.js you will need to modify the code to
render() {
return (
<View style={{ flex: 1 }}>
<Text>{this.props.passedData}</Text>
</View>
);
}

The correct way of developing a react-native app

I am a react-native newbie. I am wondering if there is a "correct" way to develop a react-native app? As the documentation is still very insufficient, I am afraid I may develop it in the very incorrect manner, and I prefer correct the mistake now, rather than after the project expands. From what I understand from my previous experience, we should not combine all pages in a single .js file, but how can each component communicate with each other?
I am currently doing like this inside index.android.js:
import Login from './Login';
import Register from './Register';
import Home from './Home';
class TheProject extends Component {
renderScene (route, navigator) {
_navigator = navigator;
switch (route.index) {
case 'Login':
return (
<View style={styles.container}>
<Login navigator={navigator} />
</View>
);
case 'Register':
return (
<View style={styles.container}>
<Register navigator={navigator} />
</View>
);
}
}
render() {
return (
<Navigator
initialRoute={{index: 'Login'}}
renderScene={this.renderScene}
/>
);
}
}
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'space-around',
backgroundColor: '#F0F0F0',
flexWrap:'wrap'
},
});
AppRegistry.registerComponent('TheProject', function() { return TheProject });
module.exports = TheProject;
and in my Login.js (other.js file will be similar):
export default class Login extends React.Component {
constructor(props) {
super(props);
this.state = {
username: '',
password: '',
};
}
registerOnPress() {
this.props.navigator.push({
index: 'Register'
});
}
loginOnPress() {
if (this.state.username != '' && this.state.password != '') {
Alert.alert('Success!', 'Successfully logged in.');
this.props.navigator.push({
index: 'Home'
});
} else {
Alert.alert('Failed to log-in', 'Wrong username or password');
}
}
render () {
return (
<View style={styles.individualContainer}>
<View style={styles.content}>
<View style={styles.formField}>
<View style={styles.input}>
<Text style={styles.label}>Username : </Text>
<View style={styles.fieldBox}>
<TextInput
style={styles.field}
underlineColorAndroid={'transparent'}
onChangeText={(data) => this.setState({ username: data })}
/>
</View>
</View>
<View style={styles.input}>
<Text style={styles.label}>Password : </Text>
<View style={styles.fieldBox}>
<TextInput
style={styles.field}
underlineColorAndroid={'transparent'}
secureTextEntry={true}
onChangeText={(data) => this.setState({ password: data })}
/>
</View>
</View>
</View>
<View style={styles.input}>
<TouchableHighlight style={styles.buttonBox} onPress={this.loginOnPress.bind(this)}>
<Text style={styles.buttonText}>Login</Text>
</TouchableHighlight>
</View>
<View style={styles.input}>
<TouchableHighlight style={styles.buttonBox} onPress={this.registerOnPress.bind(this)}>
<Text style={styles.buttonText}>Register</Text>
</TouchableHighlight>
</View>
</View>
</View>
);
}
}
I know there are a lot of ways to develop, but am I on the right track? I am quite blurred when it comes to component mount and unmount.
Your question is very vague, phrased in such a way that the only real answer is "there is no single right answer".
I suggest looking at the Awesome React Native - Seeds list for good starter kits and the Examples list as well.
Communication between components is quite straight-forwarded and is covered by Facebook's documentation on the subject.
You should definitely not develop your entire application in a single file.
Keep in mind that you do not need "React native documentation" to write react native at the beginning. First you should understand the fundamentals of React because once you do, you'll notice that those fundamentals apply identically whether you're writing a web or native app, the only thing that differs are the components used.
At first I was about to vote for closing this question, but it's somehow fascinating and tech-related if we just look through the right glasses :)
At first, you should note you have a lot of nested <View> components. This could be re-structured, where both username and password label + textinput would be applied as a component - receiving text label and onChangeText as props.
Same goes with Login and Register buttons, create them as separate component, where you define title of the button and loginOnPress/registerOnPress functions as props.
Remember to use propTypes whenever needed. This helps you and other devs to keep on track what happens in different components and how they're related to each other. For instance: Login.propTypes = { navigator: PropType.func.isRequired}
Use Flow (http://flowtype.org) with you project for types and annotations.

Categories