import { View, ScrollView, StyleSheet } from 'react-native'
import Heading from './Heading'
import Input from './Input'
class App extends Component {
constructor () {
super()
this.state = {
input value: '',
todos: [],
type: 'All'
}
inputChange (inputValue) {
this.setState({inputValue})
}
}
render () {
const {todos, inputValue, type } = this.state
return (
<View style={styles.container}>
<ScrollView keyboardShouldPersistTaps='always'
style={styles.content}>
<Heading />
<Input
input Value={inputValue}
inputChange={(text) => this.inputChange(text)} />
</ScrollView>
</View>
)
}
}
const styles = StyleSheet.create ({
container: {
flex: 1,
backgroundColor: '#f5f5f5'
},
content: {
flex: 1,
paddingTop: 60
}
})
export default App
"So I have this error that I have tried to fix through disabled eslint and it's not working. This is my first time using react-native. I'm taking a class and this is for an assignment of mine to create a TodoApp. My teacher gave us the exact code he wanted us to input into VSCode, so we could then make changes to it accordingly for the assignment. I was halfway through his video, and this error kept coming up, but not for him. I have looked all around for an answer and can't seem to find one. The section of code that gives me a problem in the inputChange (inputValue) and say it's missing a semicolon. In the video the teacher doesn't put one and it works completely fine. I've done some reading that it could be eslint, but I've tried to disable it and it still doesn't work."
With this code, you are attempting to define the method inputChange inside the constructor method, which is not possible. You need to close the constructor method definition before defining your inputChange method. I recommend taking a closer look at the code your instructor provided. I suspect that on closer inspection you will find one curly brace closing the setState function and another curly brace closing the constructor method before that inputChange method definition starts.
change position of inputChange function from inside of constructor to body of class ( after closing constructor )
class App extends Component {
constructor() {
// ...
}
inputChange(inputValue) {
// ...
}
render() {
return (
<>{/* rest of code */}</>
);
}
}
Edit
you may name properties incorrect
Related
I am trying to validate a text field on click of Submit button. But I always get the error -
TypeError: undefined is not an object (evaluating 'props.deviceLocale') on my emulator.
(I am using an Android emulator).
However I am nowhere using 'deviceLocale' in my code. I am not aware if it is required for anything I have in my code.
This is my code:
import React, {Component} from 'react';
import { View, Text, TouchableOpacity, TextInput } from 'react-native';
import ValidationComponent from 'react-native-form-validator';
export default class App extends ValidationComponent {
constructor() {
super()
this.state = {
name: "abc"
}
}
_onPressButton() {
this.validate({
name: {minlength: 3, maxlength: 7, required: true},
});
}
render() {
return (
<View>
<TextInput
ref = "name"
onChangeText = {(name) => this.setState({name})}
value = {this.state.name}
/>
<TouchableOpacity onPress = {this._onPressButton}>
<Text>Submit</Text>
</TouchableOpacity>
</View>
)
}
}
Error snap:
You are getting the error even before loading of the component then, do bind your _onPressButton correctly, then atleast your component will get mounted properly, then then your upcoming errors will follow like the use of this.validate is somewhat ambiguous to me as I cannot see validate function in the component.
To bind your _onPressed, declare it like below:
_onPressButton = () => {
this.validate({
name: {minlength: 3, maxlength: 7, required: true},
});
}
The error is causing as _onPressed is getting called as soon as your component is getting mounted. Let me know in comments if this helps you getting ahead with your component mounting atleast.
Edited:
Also, your constructor doesn't provide props to the super constructor,
Declare it like below:
constructor(props) {
super(props);
this.state = {
name: "abc"
}
}
CMD:
react-native init Test && react-native run-android
App.js:
export default class App extends Component {
render() {
new Function("person", "const { firstname } = person; alert(firstname);")({ firstname: "Test" });
}
}
Whenever the new function gets constructed and invoked, the app crashes stating: "SyntaxError: Unexpected token '{'. Expected an identifier name in const declaration" Only happens on Android.
Any help would be appreciated. Thanks!
React Native: v0.55.7
The react native documentation indicates that JavaScriptCore is generally used at runtime (V8 during debugging), but it's light on specifics as to how it is configured. One thing it does mention is that the native JavaScriptCore is used on iOS, while a different version is bundled with the app for user on Android.
Because Babel is used at compile time with react native to support ES5/ES6 features, it may be that the runtime is configured at a lower level of support. So when attempting to create code from a string at runtime, you may actually be running with a JavaScript interpreter that doesn't understand e.g., destructuring syntax.
You could try using Babel's transform at runtime to transpile your code:
import {transform} from 'babel-core';
export default class App extends Component {
render() {
const f = 'const { firstname } = person; alert(firstname);';
const result = transform(f, {
presets: ['es2015']
});
new Function("person", result.code)({ firstname: "Test" });
}
}
Can you create a const with a dynamic name? If it's possible, sorry about my lack of knowledge about that subject.
The error message said that a name to variable const is expected.
I hope it has been useful.
Best regards.
Try to change the style you create that function. In React Native is common to see arrow functions, that must be created outside your render method.
Note that your render method will be trigger every single time that your state changes. and it would be a waste of memory resources and unnecessary computing time
import React, {
Component
} from 'react';
import {
Text,
View,
StyleSheet
} from 'react-native';
export default class App extends Component {
//your custom function
myFunc = (param) => {
console.log(param)
return param
}
//your render method
render() {
const param = "Im a text"
//you could do this... i would never do that..
const myFuncInRender = () => { console.log('Im a stupid func')}
const myStupidFunc2 = new Function("person", "const { firstname } = person; alert(firstname);")({ firstname: "Test" });
return (
<View style={styles.container}>
<Text style={styles.paragraph}>
{this.myFunc(param)/* HERE is where you call the func*/}
</Text>
</View>
);
}
} // end from Class
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
padding: 8,
alignItems:'center',
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
},
});
My code is based off of this Stack Overflow question: React Native apply array values from state as Picker items
I used Manjeet Singh's first solution (for mapping an Object to Picker.Item instances) since I'm storing my data in an Object.
However, when I use his method, I'm getting a "TypeError: undefined is not an object (evaluating 'child.props.value')" error.
My code looks like:
class View extends React.Component{
state = { exercise: '' };
arrItems = {"Badminton":"7", "Basketball":"9.3", "Biking":"8"};
render(){
<Picker selectedValue={this.state.exercise}
onValueChange={(itemValue, itemIndex)=>this.setState({ exercise: itemValue })>
{Object.keys(this.arrItems).map((key) => {
return (<Picker.Item label={key} value={key} key={key}/>)
})}
}
</Picker>
}
I'm pretty new to React Native -- what is the issue causing this error?
some small tips:
Try to set your variables to the local state (this.state), at the
moment I don't think you can reach your variables. You set state inside the construtor, the constructor (as shown below) and super() lines are necessary.
You are missing a closing tag at the end of the onValueChange prop.
{ return(statement) } equals (statement), this only works if single
line.
You can use .map((item, index) => to get the index of the item as well, so that you can use it as a key prop in the Item.
Try this:
class View extends React.Component {
constructor() {
super();
this.state = {
exercise: '',
arrItems: { "Badminton": "7", "Basketball": "9.3", "Biking": "8" }
}
}
render() {
return (
<Picker selectedValue={this.state.exercise}
onValueChange={(itemValue, itemIndex) => this.setState({ exercise: itemValue })}>
{Object.keys(this.state.arrItems).map((key, index) =>
<Picker.Item label={key} value={key} key={index} />
)}
</Picker>
)
}
}
Also you might want to rename your Class to something different than View, as you will probably use the built in View a lot (can only have one).
Hi I am trying to navigate to next component using navigate function. I am using react-navigation for the navigation among multiple components.
Suppose I have index.android.js and DashboardScreen.js component. I am trying to navigate to DashboardScreen.js component from index component.
It is navigating but index component always retain in component stack. when I press back then it opens index.android.js which should not be. Does anyone know how to manage this in react-native. In Android, finish() works for this.
navigate("DashboardScreen");
When I am navigating from SplashScreen to EnableNotification then SplashScreen should be destroyed, if I am navigating from EnableNotification to CreateMessage then EnableNotification should be destroyed and if I am navigating from CreateMessage to DashboardScreen then CreateMessage should be destroyed. As of now no component is being destroyed.
index.android.js
class SplashScreen extends Component {
render() {
if (__DEV__) {
console.disableYellowBox = true;
}
const { navigate } = this.props.navigation;
AsyncStorage.getItem("#ProductTour:key").then(value => {
console.log(value);
if (value) {
navigate("DashboardScreen");
}
});
return (
....
);
}
}
const App = StackNavigator(
{
Splash: {
screen: SplashScreen,
navigationOptions: {
header: {
visible: false
}
}
},
EnableNotification: {
screen: EnableNotificationScreen,
navigationOptions: {
header: {
visible: false
}
}
},
CreateMessage: {
screen: CreateMessageScreen,
navigationOptions: {
header: {
visible: false
}
}
},
DashboardScreen: {
screen: DashboardScreen,
navigationOptions: {
header: {
visible: false
}
}
}
},
{
initialRouteName: "Splash"
}
);
Just use 'replace' in place of 'navigate'
this.props.navigation.replace('Your Next Component Name')
First of all, using AsyncStorage in an a synchronous function (most especially a lifecycle one) is such a bad idea. You should typically keep ASyncStorage to places in your folder / app structure that make sense for where you access/keep data but since that's not the question I will just mention it quickly here...
Basically you are asking to navigate once the ASync method completes itself based on EVERY render... Those new to RN should know that an awful lot of things can cause a render to fire. Some cases, the render function can fire (I have seen this many times before) 10 or more times before finalizing the last render. This means you would have fired that ASyncStorage method 10 times... definitely something to think about when implementing this stuff. So more or less, the .then(); part of the AsyncStorage function is firing long after the render has already finished doing it's thing. If it was a reasonable approach to use I would say to put the return part of the render function inside of the .then((value) => { return ( ... ); });. But this is an even worse idea. Basically you need the right lifecycle method here and it's NOT the render method.
Anyway, since I have never used this component library before I can only help nudge you in the right direction so here goes... These docs on their webpage seem to say that you need a reference to the props navigator passed down to the component in which you are using it. So if you created the navigator in this class, you would use this.refs.whateverYouNamedTheNavigatorReference.navigate('SomeItemName'). If you are in the class that has been passed this navigator as a prop, you use this.props.passNavigatorPropName.navigate('SomeItemName'). I see you are using variable deconstruction to get the navigate callback but I would caution on doing this, this way because I have seen it cause errors by grabbing an old version of the navigate function or its parent reference by accident and causing a cascading error effect.
Also, if you are going to be using ASyncStorage in a component file (again, would recommend putting this in a component/class where your data is accessed throughout the app...) and you are going to use it to decide the app should navigate forwards/backwards... definitely remove it from the render function and put it in maybe the constructor, componentWillReceiveProps, componentDidReceiveProps or componentWillUpdate lifecycle functions. That way it fires based on an update, a new passed prop obj or one time as the component is built. Anything is better than firing it every single render.
Lastly, I do not know what you have setup for your StackNavigator route stack object but you would need to have the keyword you used "DashboardScreen" in there pointing to an actual component that has been imported properly. The "DashboardScreen" keyword most likely would connect in your StackNavigator object to some component import like so...
import Dashboard from '../Views/DashboardScreenView';
StackNavigator({
DashboardScreen: {
screen: Dashboard,
path: 'dashboard/:main',
navigationOptions: null,
},
});
There is a simple way here: use "replace" (reference link repleace in navigation ,For example, you are at the screen "Login" ,
and you want to move to screen "Home", insert this code in screen "Login"
<TouchableOpacity onPress={() => { this.login() }}>
<Text}>Click me to Login</Text>
</TouchableOpacity>
and method login:
login(){
this.props.navigation.replace('Home')
}
Screen "Login" will be replaced by "Home", in Android, press Back Button =>app exit, no back screen "Login"
Based on your requirement, i suggest following setup:
SplashNavigator.js
const SplashNavigator = StackNavigator({
Splash: {
screen: SplashScreen,
navigationOptions: {
header: {
visible: false
}
}
}
});
AppNavigator.js
const AppNavigator = StackNavigator(
{
EnableNotification: {
screen: EnableNotificationScreen,
navigationOptions: {
header: {
visible: false
}
}
},
CreateMessage: {
screen: CreateMessageScreen,
navigationOptions: {
header: {
visible: false
}
}
},
Dashboard: {
screen: DashboardScreen,
navigationOptions: {
header: {
visible: false
}
}
}
},
{
initialRouteName: "EnableNotification"
}
);
In your index.android.js, you will render the SplashNavigator.
The SplashNavigator will render the SplashScreen. It has initial state value isReady set to false, so it will render a loading text until the #ProductTour:key value from AsyncStorage is loaded (AsyncStorage is async function, u should not put it in your render function). It will then render your AppNavigator and render your EnableNotification as initial route.
class SplashScreen extends Component {
constructor() {
super(props);
this.state = {
isReady: false,
}
}
componentDidMount() {
AsyncStorage.getItem("#ProductTour:key").then(value => {
console.log(value);
// you will need to handle case when `#ProductTour:key` is not exists
this.setState({
isReady: true,
});
});
}
render() {
const { isReady } = this.state;
return (
<View style={{flex: 1}}>
{
isReady ?
<AppNavigator />
: <Text>Loading</Text>
}
</View>
);
}
}
Then on EnableNotificationScreen and CreateMessageScreen, change your navigate route function to use NavigationActions.reset from doc
Example:
import { NavigationActions } from 'react-navigation';
handleOnPressButton = () => {
const resetAction = NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: "CreateMessage" })
]
});
this.props.navigation.dispatch(resetAction);
}
Yes in react native you can finish the current screen before navigating to new screen with the help of NavigationActions . Please refer this link -
http://androidseekho.com/others/reactnative/finish-current-screen-on-navigating-another-in-react-native/
SplashNavigator.js
const SplashNavigator = StackNavigator({
Splash: {
screen: SplashScreen,
navigationOptions: {
header: null}
}
}
});
Import StackActions and NavigationActions from react-navigation.
import { StackActions, NavigationActions } from 'react-navigation';
below code for performing Action
navigateToHomeScreen = () => {
const navigateAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: "HomeScreen" })],
});
this.props.navigation.dispatch(navigateAction);
}
I am trying to go back to previous view in my react native app using this code
'use strict';
var React = require('react-native');
var {
AppRegistry,
Component,
StyleSheet,
Text,
View,
BackAndroid,
Navigator
} = React;
var HomePage = require('./HomePage');
class DetailsPage extends Component{
constructor(props){
super(props);
}
render(){
return(
<View style={styles.container}>
<Text style={styles.text}>
{this.props.description}
</Text>
</View>
)
}
}
BackAndroid.addEventListener('hardwareBackPress', function() {
this.props.navigator.pop(); // line 32
return true;
});
var styles = StyleSheet.create({
container: {
flex: 1
},
text:{
color:'#000',
textAlign:'center',
fontWeight:'bold',
flex:1,
fontSize:20
},
});
module.exports = DetailsPage;
While debugging I see that the back event is detected successfully but it crashes at this line this.props.navigator.pop() giving me this error.
Cannot read property 'props' of undefinedhandleException #
D:\React\Kora\node_modules\react-native\Libraries\JavaScriptAppEngine\Initialization\ExceptionsMana…:61handleError
#
D:\React\Kora\node_modules\react-native\Libraries\JavaScriptAppEngine\Initialization\InitializeJava…:80ErrorUtils.reportFatalError
#
D:\React\Kora\node_modules\react-native\packager\react-packager\src\Resolver\polyfills\error-guard.…:28guard
#
D:\React\Kora\node_modules\react-native\Libraries\Utilities\MessageQueue.js:43callFunctionReturnFlushedQueue
#
D:\React\Kora\node_modules\react-native\Libraries\Utilities\MessageQueue.js:86onmessage
# debuggerWorker.js:39
my guess it that this.props can not be accessed out side the class braces but I don't know how to overcome this problem. if I put the BackAndroid.addEventListener inside the class it gives me error
UnExpectedToken
edit: BackAndroid is now deprecated. You should probably be using BackHandler instead.
In your event, this does not refer to what you think it refers to.
In this case, it refers to the object on which the event is called.
The way I did it in my react-native app, was by adding the event in the componentDidMount()-function of my main component (the component in which the Navigator is rendered).
I added it there the (sort of) following way:
class ViewComponent extends Component {
...
componentDidMount() {
//the '.bind(this)' makes sure 'this' refers to 'ViewComponent'
BackAndroid.addEventListener('hardwareBackPress', function() {
this.props.navigator.pop();
return true;
}.bind(this));
}
...
}
It should work like this in your project.
The componentDidMount() is fired right after the initial render. You could probably also use componentWillMount(). So it adds the event right after the first time it renders. It only gets fired off once, so there are no overlapping events and stuff like that.
I wouldn't, however, add the event listener on scenes. It brings the risk of perhaps adding the event twice. Although I'm not sure if adding that event twice would actually change anything.