React-native: how to store input value and data using AsyncStorage? - react-native

I have a form with a TextInput imported from react-native and DatePicker imported from native-base. I want to store their values on submit of the form using AsyncStorage.
I am getting an error: ReferenceError: ReferenceError:Input is not defined
This is component:
import React, { Component } from 'react';
import { View,StyleSheet, AsyncStorage, TextInput } from 'react-native';
import {
Form,
Button, Icon,
DatePicker, Text
} from 'native-base';
import PropTypes from 'prop-types';
class Reminder extends Component {
constructor(props) {
super(props);
this.state = {
input: '',
chosenDate: new Date(),
};
this.setDate = this.setDate.bind(this);
}
setDate(newDate) {
this.setState({
chosenDate: newDate
});
}
handleChangeInput = (text) => {
this.setState({input:text});
}
//On application loads, this will get the already saved data and set the state true when it's true.
componentDidMount() {
AsyncStorage.getItem("this.state.text").then((value) => {
this.setState({'this.state.text':value});
});
}
//save the input
saveData(value) {
console.log('value', value);
AsyncStorage.setItem("this.state", value);
this.setState({'this.state':value});
}
render() {
return (
<View>
<Form style={styles.formContainer}>
<View style={styles.formView}>
< TextInput
placeholder = "Set your reminder"
onChangeText={this.handleChangeInput}
value={input}
/>
<DatePicker
defaultDate={new Date()}
minimumDate={new Date(2018, 1, 1)}
maximumDate={new Date(2019, 12, 31)}
locale={"en"}
timeZoneOffsetInMinutes={undefined}
modalTransparent={false}
animationType={"fade"}
androidMode={"default"}
placeHolderText="Select date"
textStyle={{ color: "green" }}
placeHolderTextStyle={{ color: "#d3d3d3" }}
onDateChange={this.setDate}
/>
<Text style={styles.datePicker}>
{this.state.chosenDate.toString().substr(4, 12)}
</Text>
</View>
<View style={styles.footer}>
<Button block success style={styles.saveBtn}
onPress={ () =>
{this.saveData(value)
console.log('save data', value);}
}
>
<Icon type='MaterialIcons' name='done' />
</Button>
</View>
</Form>
</View>
);
}
}
const styles = StyleSheet.create({
formContainer: {
marginTop: 10,
padding: 10,
},
editIcon:{
color: '#28F1A6',
fontSize: 26,
},
editBtn:{
flex: 1,
alignSelf: 'flex-end',
},
datePicker:{
alignSelf: 'auto',
paddingLeft: 10
},
footer:{
position: 'relative',
top: 350
},
saveBtn: {
position:'relative',
marginTop: 35,
}
});
export default Reminder;
This is my screen:
import React, { Component } from 'react';
import { View, StatusBar } from 'react-native';
import PropTypes from 'prop-types';
import Reminder from '../components/Reminder';
const ReminderScreen = ({navigation}) => (
<View >
<Reminder navigation={navigation} >
<StatusBar backgroundColor = "#28F1A6" />
</Reminder >
</View>
);
Reminder.propTypes = {
navigation: PropTypes.object.isRequired
}
export default ReminderScreen;
I am fairly new to react-native. I am obviously doing missing out something, but not sure exactly what?

This is because in your TextInput component you set the props value to input instead of this.state.input
Or you can add this line before your return statement
const { input } = this.state;

Related

Flatlist data not showing up on screen

Trying to make a simple to-do list. My AddTodo component works fine and I don't believe it is causing the issue but my Flatlist does not show the data. I have no idea why as there are no errors. The issue appears with or without the scroll view.
I've tried messing around with the width and height of the items and the list itself but nothing seems to do the trick.
my mainTodo file:
import React, { Component } from 'react';
import { Text, View, StyleSheet, FlatList, ScrollView } from 'react-native';
import AddTodo from './AddTodo';
import TodoItem from './TodoItem';
class MainTodo extends Component {
constructor() {
super();
this.state = {
textInput: '',
todos: [
{ id: 0, title: 'walk rocky', completed: false },
{ id: 1, title: 'pickup dinner', completed: false }
]
};
}
addNewTodo() {
let todos = this.state.todos;
todos.unshift({
id: todos.length + 1,
todo: this.state.textInput,
completed: false
});
this.setState({
todos,
textInput: ''
});
}
render() {
return (
<View style={{ flex: 1 }}>
<AddTodo
textChange={textInput => this.setState({ textInput })}
addNewTodo={() => this.addNewTodo()}
textInput={this.state.textInput}
/>
<ScrollView>
<FlatList
style={{ flex: 1 }}
data={this.state.todos}
extraData={this.state}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) => {
return (
<TodoItem todoItem={item} />
);
}}
/>
</ScrollView>
</View>
);
}
}
export default MainTodo;
my TodoItem file:
import React, { Component } from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
class TodoItem extends Component {
render() {
const todoItem = this.props.todoItem;
return (
<View>
<TouchableOpacity style={styles.todoItem}>
<Text style={(todoItem.completed) ? { color: '#aaaaaa' } : { color: '#313131' }}>
{todoItem.title}
</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
todoItem: {
width: 40,
height: 40,
borderBottomColor: '#DDD',
borderBottomWidth: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingLeft: 15
}
});
export default TodoItem;
Under my addtodo component nothing shows up, it's just a blank screen.
In the maintodo file you are rendering the AddTodo component but i didn't see your AddTodo component. So you can update your code accordingly.
In the TodoItem remove the style applied to TouchableOpacity so that your code looks like
import React, { Component } from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
class TodoItem extends Component {
render() {
const todoItem = this.props.todoItem;
return (
<View>
<TouchableOpacity style={styles.todoItem}>
<Text style={(todoItem.completed) ? { color: '#aaaaaa' } : { color: '#313131' }}>
{todoItem.title}
</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
});
export default TodoItem;
And in the MainTodo
update your addNewTodo function as
addNewTodo = () => {
const todo = {
id: this.state.todos.length,
title: this.state.textInput,
completed: false
}
this.setState({todos: [...this.state.todos, todo ], textInput: ""})
}
create the TextInput and Button with parent View as flexDirection: "row" and so when TextInput is changed it's value is set in the textInput and when Button is pressed it will create new object and add it to the todos and set the value of TextInput to empty.
and final code can be as
import React, { Component } from 'react';
import { Text, View, StyleSheet, FlatList, ScrollView, TextInput, Button } from 'react-native';
import TodoItem from './TodoItem';
class MainTodo extends Component {
constructor() {
super();
this.state = {
textInput: '',
todos: [
{ id: 0, title: 'walk rocky', completed: false },
{ id: 1, title: 'pickup dinner', completed: false }
]
};
}
addNewTodo = () => {
const todo = {
id: this.state.todos.length,
title: this.state.textInput,
completed: false
}
this.setState({todos: [...this.state.todos, todo ], textInput: ""})
}
render() {
return (
<View style={{ flex: 1, marginTop: 30, paddingHorizontal: 20 }}>
<View style={{flexDirection: "row", alignItems: "center", justifyContent: "space-between"}}>
<TextInput style={{borderWidth: 1, borderColor: "black"}} onChangeText={textInput => this.setState({textInput})} placeholder="Enter todo text" value={this.state.textInput} />
<Button onPress={this.addNewTodo} title="Add todo" />
</View>
<FlatList
contentContainerStyle={{flexGrow: 1}}
data={this.state.todos}
extraData={this.state.todos}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) => {
return (
<TodoItem todoItem={item} />
);
}}
/>
</View>
);
}
}
export default MainTodo;
use the code
mainTodo file:
import React, { Component } from 'react';
import { Text, View, StyleSheet, FlatList, ScrollView } from 'react-native';
import AddTodo from './AddTodo';
import TodoItem from './TodoItem';
class MainTodo extends Component {
constructor() {
super();
this.state = {
textInput: '',
todos: [
{ id: 0, title: 'walk rocky', completed: false },
{ id: 1, title: 'pickup dinner', completed: false }
]
};
}
addNewTodo() {
let todos = this.state.todos;
todos.unshift({
id: todos.length + 1,
todo: this.state.textInput,
completed: false
});
this.setState({
todos,
textInput: ''
});
}
render() {
return (
<View style={{ flex: 1 }}>
<AddTodo
textChange={textInput => this.setState({ textInput })}
addNewTodo={() => this.addNewTodo()}
textInput={this.state.textInput}
/>
<ScrollView>
<FlatList
style={{ flex: 1 }}
data={this.state.todos}
extraData={this.state}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) => {
return (
<TodoItem todoItem={item} />
);
}}
/>
</ScrollView>
</View>
);
}
}
export default MainTodo;
TodoItem file:
import React, { Component } from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
class TodoItem extends Component {
render() {
const todoItem = this.props.todoItem;
return (
<View>
<TouchableOpacity style={styles.todoItem}>
<Text style={(todoItem.completed) ? { color: '#aaaaaa' } : { color: '#313131' }}>
{todoItem.title}
</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
todoItem: {
width: 40,
height: 40,
borderBottomColor: '#DDD',
borderBottomWidth: 1,
backgroundColor:'red',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingLeft: 15
}
});
export default TodoItem;

Cant find the variable React-native

native . I made the status component and router.js file .The emulator giving me error Cant find varible i do not know what is the problem but im getting this error in emulator .
here is my code
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
import StatusComponent from './component/StatusComponent';
import HeaderComponent from './component/headerComponent';
import Router from './component/Router';
import MainPage from './component/MainPage';
export default class Point extends Component {
render() {
return (
<View style={{flex: 1,backgroundColor: 'white'}}>
<StatusComponent/>
<HeaderComponent/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
} );
AppRegistry.registerComponent('Point', () => Point);
and here is my status component
import React,{ Component } from 'react';
import {
Text,
View,
StyleSheet
} from 'react-native';
export class StatusComponent extends Component{
render()
{
return(
<View style={styles.Bar}>
</View>
)
};
}
export default StatusComponent;
const styles=StyleSheet.create({
Bar:{
backgroundColor: 'white',
height: 20
}
})
here is code for Router.Js this file cousing the issue
import React, { Component } from 'react'
import {
StyleSheet,
Text,
Navigator,
TouchableOpacity
} from 'react-native'
import MainPage from './MainPage'
import Sports from './Sports'
export default class Router extends Component {
constructor(){
super()
}
render() {
return (
<Navigator
initialRoute = {{ name: 'MainPage', title: 'MainPage' }}
renderScene = { this.renderScene }
navigationBar = {
<Navigator.NavigationBar
style = { styles.navigationBar }
routeMapper = { NavigationBarRouteMapper } />
}
/>
);
}
renderScene(route, navigator) {
if(route.name == 'MainPage') {
return (
<MainPage
navigator = {navigator}
{...route.passProps}
/>
)
}
if(route.name == 'Sports') {
return (
<Sports
navigator = {navigator}
{...route.passProps}
/>
)
}
}
}
var NavigationBarRouteMapper = {
LeftButton(route, navigator, index, navState) {
if(index > 0) {
return (
<TouchableOpacity
onPress = {() => { if (index > 0) { navigator.pop() } }}>
<Text style={ styles.leftButton }>
Back
</Text>
</TouchableOpacity>
)
}
else { return null }
},
RightButton(route, navigator, index, navState) {
if (route.openMenu) return (
<TouchableOpacity
onPress = { () => route.openMenu() }>
<Text style = { styles.rightButton }>
{ route.rightText || 'Menu' }
</Text>
</TouchableOpacity>
)
},
Title(route, navigator, index, navState) {
return (
<Text style = { styles.title }>
{route.title}
</Text>
)
}
};
const styles = StyleSheet.create({
navigationBar: {
backgroundColor: 'blue',
},
leftButton: {
color: '#ffffff',
margin: 10,
fontSize: 17,
},
title: {
paddingVertical: 10,
color: '#ffffff',
justifyContent: 'center',
fontSize: 18
},
rightButton: {
color: 'white',
margin: 10,
fontSize: 16
}
})
In the StatusComponent file, you have export in front of the class StatusComponent extends Component. You should remove that export and leave the export default StatusComponent; at the bottom.
If after that, it still doesn't work then check the absolute path you are using to import the StatusComponent. Make sure it's correct
there is mistake in statusComponent file and thats very stupid mistake

How do I pass strings from one component to another component?

Login component:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
TouchableHighlight,
TextInput,
Image
} from 'react-native';
var DisplayData = require('./DisplayData');
export default class Login extends Component{
constructor(props){
super(props)
this.state = {
Latitude: '',
Longitude: '',
}
}
onPressDisplayData() {
this.props.navigator.push({
name: 'DisplayView',
component: DisplayData
});
}
render() {
return (
<View style = {styles.container}>
<Image source={require('./logo.png')}/>
<TextInput
style = {styles.input}
placeholder = 'Latitude'
autoCapitalize = 'none'
onChangeText={(text) => this.setState({Latitude:text})}
/>
<TextInput
style = {styles.input}
placeholder = 'Longitude'
autoCapitalize = 'none'
onChangeText={(text) => this.setState({Longitude:text})}
/>
<TouchableHighlight
style = {styles.submit}
onPress = {() => this.onPressDisplayData()
}
>
<Text>
Submit
</Text>
</TouchableHighlight>
</View>
);
}
}
const styles = StyleSheet.create ({
container: {
flex: 1,
alignItems: 'center',
justifyContent:'center',
paddingBottom: 40
},
input: {
margin: 15,
height: 40,
borderColor: 'grey',
borderWidth: 1
},
submit: {
backgroundColor: '#FFDD03',
padding: 10
}
})
module.exports = Login;
DisplayData component:
import React, {
Component,
} from 'react';
import {
AppRegistry,
Image,
ListView,
StyleSheet,
Text,
View,
} from 'react-native';
var REQUEST_URL = 'http://api.geonames.org/earthquakesJSON?north='+4+'&south='+-9.9+'&east='+-22.4+'&west='+55.2+'&username=afdsanfd'
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
class DisplayData extends Component {
constructor(props){
super(props)
this.state = {
earthquakes: ds.cloneWithRows([])
};
}
componentDidMount() {
fetch(REQUEST_URL)
.then((response) => response.json())
.then((responseData) => this.setState({ earthquakes: ds.cloneWithRows(responseData.earthquakes) }))
.catch(function(error) {
console.warn(error);
});
}
render() {
return (
<View>
<ListView
dataSource = {this.state.earthquakes}
renderRow={(rowData) => (
<View style={{flex: 1, paddingTop: 10, paddingBottom: 10, borderWidth: 0.5, paddingLeft: 10, borderColor: '#D3D3D3'}}>
<Text style={{fontSize: 25}}>{rowData.src}</Text>
<Text>DateTime: {rowData.datetime}</Text>
<Text>Magnitude: {rowData.magnitude}</Text>
<Text>EqID: {rowData.eqid}</Text>
<Text>Depth: {rowData.depth}</Text>
</View>
)}
/>
</View>
);
}
}
module.exports = DisplayData;
So what I am trying to accomplish through this app is having someone enter latitude and longitude such that an API call (REQUEST_URL) that'd return earthquake info. However, i'm struggling really hard with passing the entered latitude and longitude into the DisplayData component. I've tried things such as creating a global latitude and longitude but none have been working.

React-Native Navigator Android Error

Native app development
This is what I tried
File: index.android.js
/**
* Sample React Native App
* https://github.com/facebook/react-native
* #flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Navigator,
TouchableHighlight,
Text,
View
} from 'react-native';
var Loader = require('./app/components/Loader');
var Login = require('./app/components/Login');
export default class Demo extends Component {
constructor(props) {
super(props);
}
render() {
return (
<Navigator>
initialRoute = {{
id:'Loader',
}}
renderScene = {(route, navigator) => {
_navigator = navigator;
switch (route.id){
case 'Loader':
return (<Loader navigator={navigator} route={route} title="Loader"/>);
case 'Login':
return (<Login navigator={navigator} route={route} title="Login"/>);
}
}
}
</Navigator>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('Demo', () => Demo);
My Loader Component :
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
Image
} from 'react-native'
class Loader extends Component{
constructor(props) {
super(props);
this.state = {
id: 'Loader'
}
}
render(){
return(
<View style={styles.container}>
<Image source={require('../assets/img/ace-logo-white-01.png')} style={styles.logo}/>
<Text style={styles.loadingText}>Loading...</Text>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: 'red'
},
logo: {
height: 30,
width: 50
},
loadingText: {
flex:1,
fontSize: 25,
paddingTop: 20,
color: 'white'
}
});
module.exports = Loader;
when I run the app I am getting error undefined is not a funtion(evaluating 'this.props.renderScene(route,this)')
I have tried this by watching some tutorials on Youtube but I can't find the answer to my problem.
What I want to do is when the app is launched the Loader component I made should load and then from loader component I redirect user to the Login componet but currently I am not able to load any component as it loads with the error I stated above.
Here is a sample code for you:
render() {
return (
<Navigator
initialRoute={{ id: 'Sample', name: 'Index' }}
renderScene={this.renderScene.bind(this)}
configureScene={(route, routeStack) => Navigator.SceneConfigs.FloatFromRight}
/>
); }
renderScene = (route, navigator) => {
if (route.id === 'Sample') {
return (
<Sample
navigator={navigator}
/>
);
}
}
You may have made some syntax mistakes with the code given by #JainZz. Try this
import Loader from './app/components/Loader'
export default class Demo extends Component {
constructor(props) {
super(props);
}
render() {
return (
<Navigator
initialRoute={{ id: 'Loader', name: 'Loader' }}
renderScene={this.renderScene.bind(this)}
configureScene={(route, routeStack) => Navigator.SceneConfigs.FloatFromRight}
/>
);
}
renderScene = (route, navigator) => {
if (route.id === 'Loader') {
return (
<Loader
navigator={navigator}
/>
);
}
}
}

React Native `alignItems: 'flex-end'` hides content in TabBarIOS component

This question is similar to this one however I have different requirements. I have a <TabBarIOS> component that renders a <Camera> from react-native-camera. I need to place a button to take a picture at the bottom of the <Camera> component but above the <TabBarIOS> component.
index.ios.js
import React, { Component } from 'react';
import {
AppRegistry,
TabBarIOS,
ScrollView,
StyleSheet,
Text,
View
} from 'react-native';
import CameraTab from './views/CameraTab.ios.js';
import FilesTab from './views/FilesTab.ios.js';
import Icon from 'react-native-vector-icons/MaterialIcons';
export default class MyApp extends Component {
constructor(props) {
super(props);
this.state = {
selectedTab: 'cameraTab'
};
};
_renderContent() {
switch (this.state.selectedTab) {
case "filesTab":
return <FilesTab style={styles.tabContent}></FilesTab>;
case "cameraTab":
return <CameraTab style={styles.tabContent}></CameraTab>;
case "settingsTab":
return <View style={styles.tabContent}></View>;
default:
return <View style={styles.tabContent}></View>;
}
};
render() {
return (
<TabBarIOS
tintColor="#3498db"
barTintColor="#ecf0f1">
<Icon.TabBarItemIOS
title="Files"
iconName="folder"
selected={this.state.selectedTab === "filesTab"}
onPress={() => {
this.setState({
selectedTab: "filesTab",
});
}}>
{this._renderContent()}
</Icon.TabBarItemIOS>
<Icon.TabBarItemIOS
title="Camera"
iconName="photo-camera"
badge={this.state.notifCount > 0 ? this.state.notifCount : undefined}
selected={this.state.selectedTab === "cameraTab"}
onPress={() => {
this.setState({
selectedTab: "cameraTab",
notifCount: this.state.notifCount + 1,
});
}}>
{this._renderContent()}
</Icon.TabBarItemIOS>
<Icon.TabBarItemIOS
title="Settings"
iconName="settings"
selected={this.state.selectedTab === 'settingsTab'}
onPress={() => {
this.setState({
selectedTab: "settingsTab",
presses: this.state.presses + 1
});
}}>
{this._renderContent()}
</Icon.TabBarItemIOS>
</TabBarIOS>
);
}
}
var styles = StyleSheet.create({
tabContent: {},
});
AppRegistry.registerComponent('myapp', () => myApp);
CameraTab.ios.js
import React, { Component } from 'react';
import {
Dimensions,
StyleSheet,
Text,
View
} from 'react-native';
import Camera from 'react-native-camera';
export default class CameraTab extends Component {
constructor(props) {
super(props);
this.state = {};
};
render() {
return (
<Camera
ref={(cam) => {
this.camera = cam;
}}
style={styles.preview}
aspect={Camera.constants.Aspect.fill}>
</Camera>
);
}
takePicture() {
this.camera.capture()
.then((data) => console.log(data))
.catch(err => console.error(err));
}
}
var styles = StyleSheet.create({
preview: {
flex: 1,
flexDirection: 'row',
alignItems: 'flex-end',
height: Dimensions.get('window').height,
width: Dimensions.get('window').width
},
capture: {
backgroundColor: '#fff',
borderRadius: 5,
color: '#000',
height: 20
}
});
module.exports = CameraTab;
I've tried various things but the capture button is always hidden when alignItems: 'flex-end' is in the container component's style.
It should look something like this:
Edit: I've discovered this issue that describes a workaround (placing the button component outside of the camera component). According to RN's docs on Height and Width it seems that this solution will work for all screen dimensions. However this doesn't work for me because I want a Subview with icons inside the camera.
OK, finally fixed it. I think the problem had to do with the height and width in the preview style. Working code:
import React, { Component } from 'react';
import {
Dimensions,
StyleSheet,
Text,
TouchableHighlight,
View
} from 'react-native';
import Camera from 'react-native-camera';
import Icon from 'react-native-vector-icons/Ionicons';
export default class CameraTab extends Component {
constructor(props) {
super(props);
this.state = {};
};
render() {
return (
<View style={styles.container}>
<Camera
ref={(cam) => {
this._camera = cam;
}}
style={styles.preview}
aspect={Camera.constants.Aspect.fill}
captureTarget={Camera.constants.CaptureTarget.disk}>
<TouchableHighlight
style={styles.cameraButton}
onPress={this._takePicture.bind(this)}>
<Icon name="ios-qr-scanner" size={55} color="#95a5a6" />
</TouchableHighlight>
</Camera>
</View>
);
}
_takePicture() {
this._camera.capture()
.then((data) => {
console.log(data)
})
.catch((err) => {
console.error(err)
});
}
}
var styles = StyleSheet.create({
cameraButton: {
flex: 0,
flexDirection: 'row',
marginBottom: 60,
},
container: {
flex: 1,
},
preview: {
flex: 1,
flexDirection: 'row',
alignItems: 'flex-end',
justifyContent: 'space-around'
},
});
module.exports = CameraTab;