storing data on iOS device using react native - ios

I am new to React Native and trying to create a simple iOS app. The app has a button on clicking which I need to store the timestamp of the click on the device in a file.
I know that React Native has an API called AsyncStorage but I am getting errors while using this. I copied the code from some site on the net.
Can someone please guide me to use this API?
This is my entire code:
import React, {Component} from 'react';
import { StyleSheet, Text, View, TextInput, AsyncStorage } from 'react-native';
export default class App extends Component{
state = {
'name': ''
}
componentDidMount = () => AsyncStorage.getItem('name').then((value) => this.setState({'name': value}))
setName = (value) => {
AsyncStorage.setItem('name': value);
this.setState({'name': value});
}
render() {
return (
<View style={styles.container}>
<TextInput style = {styles.textInput} autoCapitalize = 'none'
onChangeText = {this.setName}/>
<Text>
{this.state.name}
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
marginTop: 50
},
textInput: {
margin: 15,
height: 35,
borderWidth: 1,
backgroundColor: '#7685ed'
}
});
As for the error, when I launch the code on iOS, I am getting a red screen. There is no syntax error that I can see.
Thanks in advance.

Hard to say without more detail the exact problem you're facing, but I assume some of the following might help you?
Ah I see you posted some code. You will need a constructor that defines your state as well. Added it in my code below.
Please note I'm not an expert. Forgive any errors
import {
AsyncStorage,
} from 'react-native';
class myComponent extends React.Component{
constructor(props) {
super(props);
this.state = {
data: null
};
}
componentDidMount() {
this._loadInitialState().done();
}
_someFunction() {
var myData = 123;
saveItemLocally('data', myData);
}
async _loadInitialState() {
try {
// get localy stored data
var dataStored = await AsyncStorage.getItem('data');
if (dataStored!==null) {
this.setState({
data: dataStored
});
}
} catch (error) {
//didn't get locally stored data
console.log(error.message);
}
} // end _loadinitialstate
render () {
//your render function
return (
);
}
} // end of your component
async function saveItemLocally(item, value) {
try {
await AsyncStorage.setItem(item, value);
} catch (error) {
console.log('AsyncStorage error: ' + error.message);
}
}

Related

React-Native navigation.addListener is not a functio

Is there a way I can fix this without using redux?
This is only happening on iOS, on android the AddListener works perfectly fine without it.
I have a component and I call the props.navigation.addListener on the componentDidMount functon.
Some code to help understand exactly where it breaks:
componentDidMount(){
var _this = this;
this.willBlurListener = this.props.navigation.addListener('willBlur', () => {
_this.timer.clearTimeout();
});
this.willFocusListener = this.props.navigation.addListener('willFocus', () => {
_this._action();
});
AppState.addEventListener('change', this._handleAppStateChange);
}
And then I use the component like this:
<Inactivity name='SomeNameView' navigation={ this.props.navigation }>
{this.renderDetails()}
</Inactivity>
Can you please try to use withNavigation function, it returns a HOC that has navigation in it props so you don't have to pass from the parent component to the child:
I created a simple app that uses this concept that probably can help you:
import React from 'react';
import {
View,
Text,
Button,
} from 'react-native';
import {
createStackNavigator,
withNavigation,
} from 'react-navigation';
class SomeComponent extends React.Component {
componentDidMount() {
this.willBlurListener = this.props.navigation.addListener('willBlur', () => {
this.someAction();
})
}
someAction() {
console.log('Some action is called!');
}
componentWillUnmount() {
this.willBlurListener.remove();
}
render() {
return (
<View>
<Text>Some Component</Text>
<Button
title={'Open settings'}
onPress={() => this.props.navigation.navigate('Settings')}
/>
</View>
)
}
}
const SomeComponentWithNavigation = withNavigation(SomeComponent);
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Home'
}
render() {
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<SomeComponentWithNavigation/>
<Text>Welcome to home screen!</Text>
</View>
)
}
}
class SettingsScreen extends React.Component {
static navigationOptions = {
title: 'Settings'
}
render() {
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text>Welcome to settings screen!</Text>
</View>
)
}
}
export default createStackNavigator(
{
Home: HomeScreen,
Settings: SettingsScreen,
},
);
I have used import { useNavigation } from '#react-navigation/native'; to achieve this. This could work for you as well.
Sample code example
import { useNavigation } from '#react-navigation/native';
class CurrentOrderClass extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
this.onFocusSubscribe = this.props.navigation.addListener('focus', () => {
// Your code
});
}
componentWillUnmount() {
this.onFocusSubscribe();
}
.
.
.
.
function CurrentOrder(props) {
const navigation = useNavigation(props)
return <CurrentOrderClass {...props} navigation={navigation} />
}
}
export default CurrentOrder;
You can also check to React Native docs https://reactnavigation.org/docs/navigation-events/
I found this a bit tricky and after looking into it for a bit, I come up with the following solution. Note that is tested on React Navigation 5.x.
import { useIsDrawerOpen } from "#react-navigation/drawer";
let lastDrawerStateIsOpened = false;
const DrawerComponent = (props) => {
const isOpened = useIsDrawerOpen();
if (lastDrawerStateIsOpened != isOpened) {
lastDrawerStateIsOpened = isOpened;
if (isOpened) {
// Do what needs to be done when drawer is opened.
}
}
};
Also, note that I'm using a functional component.

Rendering user post JSON data in react native

Hello i'm currently working with React native using my rails api to retrieve user micropost data. The data renders in my log but comes up blank in react native. Honestly not sure what i'm doing wrong. can anyone help? Maybe the JSON is the problem?
Here is the JSON data:
[{"id":4,"content":"fool","user_id":1,"created_at":"2018-06-21T00:50:08.343Z","updated_at":"2018-06-21T00:50:08.343Z","picture":{"url":null}},{"id":3,"content":"pool\r\n","user_id":1,"created_at":"2018-06-21T00:50:04.644Z","updated_at":"2018-06-21T00:50:04.644Z","picture":{"url":null}},{"id":2,"content":"cool","user_id":1,"created_at":"2018-06-16T04:26:11.020Z","updated_at":"2018-06-16T04:26:11.020Z","picture":{"url":null}}]
And Here is my React Native code:
import React, { Component } from "react";
import { FlatList, StyleSheet, Text, View, AsyncStorage } from "react-
native";
const ACCESS_TOKEN = 'access_token';
export default class App extends Component {
state = {
data: []
};
componentWillMount() {
this.fetchData();
}
fetchData = async () => {
let accessToken = await AsyncStorage.getItem(ACCESS_TOKEN);
const response = await fetch("https://example.com/api/users/"+accessToken);
const json = await response.json();
this.setState({ data: json.data });
};
render() {
return (
<View style={styles.container}>
<FlatList
data={this.state.data}
keyExtractor={item => item.toString()}
renderItem={({ item }) =>
<Text>
//also tried {`${item.content}`}, didn't work
{`${item.microposts.content}`}
</Text>}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
marginTop: 15,
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#F5FCFF"
}
});
Remove the extra }
Please optimize code by declaring renderItem as such
renderItem={({ item }) => <Text>{item.microposts && item.microposts.content}</Text>}

Rendering JSON data in react native

I'm currently using my api to render all posts in JSON to react native. But I keep getting this undefined error. And sometimes the data just wont render. Can anyone give me any help on rendering this data in react native? And explain to me what i'm doing wrong? I'm pretty new with JSON. Thanks :)
Here is my JSON:
{"data":[{"id":"1","type":"posts","links":{"self":"https://example.com/posts/1"},"attributes":{"title":"Laughter Post","context":{}},"relationships":{"user":{"links":{"self":"https://example.com/posts/1/relationships/user","related":"https://example.com/posts/1/user"}}}}]}
And here is my react native code:
import React, { Component } from "react";
import { FlatList, StyleSheet, Text, View } from "react-native";
export default class App extends Component {
state = {
data: []
};
componentWillMount() {
this.fetchData();
}
fetchData = async () => {
const response = await fetch("https://example.com/posts.json");
const json = await response.json();
this.setState({ data: json.data });
};
render() {
return (
<View style={styles.container}>
<FlatList
data={this.state.data}
keyExtractor={item => item.toString()}
renderItem={({ item }) =>
<Text>
{`${item.title}`}
</Text>}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
marginTop: 15,
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#F5FCFF"
}
});
It seems you are accessing title directly from the root, but it is inside key attributes
It should be
{`${item. attributes.title}`}
Or else if you can tell us the exact error, we can help you more regarding this issue.

Why react doesn't show Image from url local

hello every one I have an application running locally with RoR everything works fine in the backend, also I can see the Json in Postman
http://127.0.0.1:3000/api/v1/articles
[
{
"id": 1,
"title": "Barack Obama",
"description": "Sabias que? el era muy pobre",
"avatar_content_type": "/system/articles/avatars/000/000/001/original/user-two.png?1509755893"
}
]
and also in my mobile emulator I can see the Title and description that's mean everything works fine. BUT I can't see the image :/ some advice?
ProductList.js
// step 1: import libraries
import React, { Component } from 'react';
import { ScrollView } from 'react-native';
import Product from './Product';
export default class ProductList extends Component {
state = {
products: []
}
componentDidMount() {
return fetch('http://MYIP:3000/api/v1/articles')
.then((response) => response.json())
.then((responseJson) => {
this.setState({products: responseJson})
})
}
render() {
var productList = this.state.products.map(function(item) {
return (
<Product title = { item.title }
description = { item.description }
image_url = { item.avatar_content_type }
key = { item.id }/>
)
})
return (
<ScrollView>
{ productList }
</ScrollView>
);
}
}
Product.js
// step 1: import libraries
import React, { Component } from 'react';
import { StyleSheet, Text, View, Alert, Image } from 'react-native';
// step 2: create component
export default class Product extends Component {
render() {
return (
<View>
<Image source={{uri: this.props.image_url }} style={{width: 60,height: 60,}}/>
<Text style = { style.textStyle }>{ this.props.title }</Text>
<Text style = { style.textStyle }>{ this.props.description }</Text>
</View>
);
}
}
const style = StyleSheet.create({
textStyle: {
fontSize: 20,
padding: 20
},
amountStyle: {
fontSize: 15,
paddingLeft: 20
}
})
I dont get exceptions or something similar, I'm not just be able to see the Image in my mobile emulator
It may be because It is empty during the first render as you are trying to perform an asynchronous operation
So what you could do is u can check by giving a condition I normally do it with lodash using _.isEmpty method
try this:
<Image source={{uri: (_.isEmpty(this.props.image_url) ? null : this.props.image_url) }}

React native doesn't show {this.state.age} in Text

React native won't display any of my States in or . But they're working with functions.
That is in my Code:
import {
StyleSheet,
View,
Image,
Text, //Important
PanResponder,
Animated,
Dimensions,
Button,
Slider,
TouchableWithoutFeedback,
Alert,
TouchableOpacity,
TouchableHighlight,
Modal, // Important
} from 'react-native'
My Constructor:
constructor(props) {
super(props);
this.state = {ModalMenu: false};
this.state = {ModalKunst: false};
this.state = {ModalArtwork: false};
this.state = { viewRef: null };
this.state = { age: 150 };
this.state = { farbe: 'black'};
this.state = {ModalPrice: false};
this.state = {
TextInputName: '',
TextInputEmail: '',
}
this.state = {
TextInputName2: '',
TextInputEmail2: ''
}
}
To display the State:
render() {
const {birthday, name, bio, id, id2} = this.props.profile
const profileAge = this.calcAge(birthday)
var fbImage = require('./img/bild12.jpg')
const rotateCard = this.pan.x.interpolate({
inputRange: [-200, 0, 200],
outputRange: ['10deg', '0deg', '-10deg'],
})
const animatedStyle = {
transform: [
{translateX: this.pan.x},
{translateY: this.pan.y},
{rotate: rotateCard},
]
}
return (
<View><Text>{this.state.age}</Text></View>
);
}}
But its showing nothing :(
I also don't get an error
Would be very nice if someone could help me out with that.
I updated all the render code
In the constructor please do all your initialization at once. Every this.state = {} statement is overriding the previous this.state
replace your constructor with following code.
this.state = {
ModalMenu: false,
ModalKunst: false,
viewRef: null,
age: 150,
farbe: 'black',
ModalPrice: false
};
Heres a sample code try this..
import React, { Component } from 'react';
import { Text, View, StyleSheet } from 'react-native';
export default class App extends Component {
constructor(){
super();
this.state = {age: '25'};
}
render() {
return (
<View >
<Text style={styles.paragraph}>
{this.state.age}
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
paragraph: {
margin: 44,
fontSize: 20,
fontWeight: 'bold',
textAlign: 'center',
color: '#34495e',
},
});
Your render method doesn't return anything. Add return inside
render method.
change this:
render() {
*not important*
}
to:
render() {
return (
<View><Text>{this.state.age}</Text></View>
);
}
At the moment, you are continually overriding your state, I've tidied your code up a bit below, here are some points to note about what I've done...
You need to import React from 'react' to utilise 'Component' as your class needs to extend from this.
You need to use a class as you have state
You can import an image like I've done below with fbImage
It's good habit to have say what is your exported default in each component you make.
You don't need to call constructor and super, just simply doing state = {} will do this for you
Place all your state within one state object, don't keep recalling state
Think about your general code formatting (in terms of how it looks) easier code to read will help you identify errors more easily!
import React from 'react'
import {
StyleSheet,
View,
Image,
Text, //Important
PanResponder,
Animated,
Dimensions,
Button,
Slider,
TouchableWithoutFeedback,
Alert,
TouchableOpacity,
TouchableHighlight,
Modal, // Important
} from 'react-native'
import fbImage from './img/bild12.jpg'
export default class App extends React.Component {
state = {
age: 150,
farbe: 'black',
ModalArtwork: false,
ModalKunst: false,
ModalMenu: false,
ModalPrice: false,
TextInputName: '',
TextInputEmail: '',
TextInputName2: '',
TextInputEmail2: '',
viewRef: null,
}
render() {
const {birthday, name, bio, id, id2} = this.props.profile
const profileAge = this.calcAge(birthday)
const rotateCard = this.pan.x.interpolate(
{
inputRange: [-200, 0, 200],
outputRange: ['10deg', '0deg', '-10deg'],
}
)
const animatedStyle = {
transform: [
{translateX: this.pan.x},
{translateY: this.pan.y},
{rotate: rotateCard},
]
}
return (
<View>
<Text>
{this.state.age}
</Text>
</View>
)
}
}

Resources