how to implement crud axios in react native using react native class component? (API) - react-native

can anyone help me,
i am trying to make a simple CRUD using axios react native with class component,
to pass data from GET to Details data I succeeded, but when on the DETAIL page to retrieve only one data I had problems,
when I try console.log(dataTampung) / console.warn(dataTampung), the data array appears, but we want to display it instead of undefined.
import React, { Component } from 'react'
import { Text, View } from 'react-native'
import axios from 'axios'
export class DetailData extends Component {
constructor(props) {
super(props)
this.state = {
dataTampung: []
}
}
componentDidMount (){
this.getData();
}
getData = () => {
axios.get('http:my_local_ip_endpoind/api.php?on=detail&id='+this.props.route.params.id)
.then( response => {
this. setState({
dataTampung:response.data.data.result
})
})
.catch(function (error) {
console.log(error);
});
}
render() {
const { id } = this.props.route.params;
const { dataTampung } = this.state;
console.warn(dataTampung);
return (
<View>
<Text> This ID = {id} </Text>
<Text> Title = {`${dataTampung.title}`} </Text>
</View>
)
}
}
export default DetailData
And this is how it appears:enter image description here
Please help :(
I apologize in advance for my bad English.

You are trying to access the array with a dot notation. First, access the specific index in the array in thing case dataTampung[0] which will give you the object, then you can access the title as dataTampung[0].title.

Related

React native How to execute function every time when i open page

I need to send request every time when i open page. Currently when i access page first time after load the app everything is ok, but if i go to another page and back after that request is not send it again.
You have to add focus listener so when you go back, It will refresh the data like
import * as React from 'react';
import { View } from 'react-native';
function AppScreen({ navigation }) {
React.useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
// The screen is focused
// Call any action and update data
});
// Return the function to unsubscribe from the event so it gets removed on unmount
return unsubscribe;
}, [navigation]);
return <View />;
}
source : https://reactnavigation.org/docs/function-after-focusing-screen/
Here you go, example for a class based and functional based component to run something on every load of the screen.
import React, { useEffect } from "react";
import {View} from 'react-native'
//Functional Component
const App = () =>
{
useEffect(() =>
{
myAction();
}, [])
return (
<View>
</View>
);
}
//Class based Component
class App extends Component
{
componentDidMount()
{
this.myAction();
}
render()
{
return(
<View>
</View>
)
}
}

How to change react native app layout from api

I have developed an store app, my boss wants a feature that from wordpress panel select predefined layout to change the whole design and choose which category to be first or .... .
I have created all designs and components that needed, but I do not know how to change app layout that I recieved from api, is there any code or help for that. This change is not about color , its about changing whole home page app layout
Sorry for my english
Here is a simple example that you could implement.
You'll need to create custom complete components for each layout for the homepage.
Then you'll need to call the Wordpress API to get the layout name that needs to be displayed.
import React, { PureComponent } from 'react';
import { AppRegistry } from 'react-native';
import Layout1 from './components/Home/Layout1';
import Layout2 from './components/Home/Layout2';
import Layout3 from './components/Home/Layout3';
import Layout4 from './components/Home/Layout4';
import Loading from './components/Loading';
class HomePage extends PureComponent {
constructor(props) {
super(props);
this.state = {
layout: null
};
}
async componentDidMount() {
const response = await fetch('https://example.com/wp-json/whatever-api-endpoint')
.then(r => r.json());
this.setState({
layout: response
});
}
getContentElement = () => {
switch (this.state.layout) {
case 'layout_1': return <Layout1 />;
case 'layout_2': return <Layout2 />;
case 'layout_3': return <Layout3 />;
case 'layout_4': return <Layout4 />;
default: return <Loading />
}
};
render() {
const contentElement = this.getContentElement();
return (
<View>
{contentElement}
</View>
);
}
}
AppRegistry.registerComponent('MyApp', () => HomePage);

Persisting data between app launches with Expo & React Native

Here's my App.js, everything else is as standard/simple as I can get it.
import React from 'react';
import { AsyncStorage, Text, View } from 'react-native';
export default class App extends React.Component {
render() {
console.log("Fetching data")
AsyncStorage.getItem('#MySuperStore:key', (value) => {
console.log("Fetched data: ", value)
if(value == null) {
console.log("Writing data!")
AsyncStorage.setItem('#MySuperStore:key', 'data', () => {
console.log("Wrote data!")
})
}
})
return(
<View>
<Text>Hello, ReplIt</Text>
</View>
);
}
}
The fetched value is always null.
I've tried this both locally and on ReplIt. In all cases, the data does not persist across app loads; I always see:
Fetching data
Fetched data: null
Writing data!
Wrote data!
What am I doing wrong? Do I have an incorrect assumption about how Expo interacts with the persistent storage? AFAIK, AsyncStorage is supposed to save stuff to the device; so I can close and re-open the app and have the data persist.
UPD: i just realized your code worked as expected... probably it is replit issue as mentioned in comment.
Avoid any requests and async calls in render method, because it could be called may times depending on how props or state changing. Better put all related code into componentDidMount as it is recommended in documentation. It will be called only once when component mounted.
Not sure why your code dodnt worked for you, callbacks are allowed for AsyncStorage, however wait works just fine for me:
import React from "react";
import { AsyncStorage, Text, View } from "react-native";
export default class App extends React.Component {
constructor() {
super();
this.state = {
storedValue: null
};
}
async componentDidMount() {
let storedValue = await AsyncStorage.getItem("#MySuperStore:key");
console.log("Fetched data: ", storedValue);
if (storedValue == null) {
console.log("Writing data!");
storedValue = await AsyncStorage.setItem("#MySuperStore:key", "data");
}
this.setState({
storedValue
});
}
render() {
const { storedValue } = this.state;
return (
<View>
<Text>Hello, ReplIt</Text>
<Text>This is Stored Value, '{storedValue}'</Text>
</View>
);
}
}
give these a try. AsyncStorage is a Javascript Promise based method.
AsyncStorage.getItem('#MySuperStore:key')
.then(value => console.log(value))
or
value = await AsyncStorage.getItem('#MySuperStore:key');
console.log(value);

When to make a Fetch call for React Native Component

I'm new to React Native and confused on how to properly utilize the provided Fetch API.
The call itself (as outlined here: http://facebook.github.io/react-native/docs/network.html) is straightforward, and I can log out a successful response, but when it comes time to render the data, it's undefined.
I would expect that I could define an empty 'movies' array, and then replace it by calling 'setState' from componentDidMount(), which would trigger a re-render. Is this assumption incorrect?
The code sample below results in the following error:
'undefined is not an object (evaluating 'allRowIDs.length')
Thanks in advance for any help!
import React, { Component } from 'react';
import { AppRegistry, ListView, Text, View } from 'react-native';
class ReactNativePlayground extends Component {
constructor() {
super();
this.state = {
movies: []
}
}
componentDidMount() {
fetch('https://facebook.github.io/react-native/movies.json')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
movies: responseJson.movies
})
})
.catch((error) => {
console.error(error);
});
}
render() {
return (
<View>
<Text>test</Text>
<ListView
dataSource={this.state.movies}
renderRow={(row) => <Text>{row.title}</Text>}
/>
</View>
)
}
}
AppRegistry.registerComponent('ReactNativePlayground', () => ReactNativePlayground);
That's because you need to place the data into a ListView.DataSource:
constructor (props) {
super(props);
const ds = new ListView.DataSource({
rowHasChanged: (a, b) => a !== b
})
this.state = {
movies: ds.cloneWithRows([])
}
}
// Inside the response JSON:
this.setState({
movies: this.state.movies.cloneWithRows(responseJson.movies)
});
The React Native ListView docs demonstrate this kind of setup. Using the datasource allows for optimisations to be made when rendering lists of data (notice the rowHasChanged function for instance - which prevents needless re-rendering of a row when the data hasn't altered.

State change not making it to the child container

In my react native app I'm using redux to handle state transition of a Post object -- the state is changed by couple of child components. The Post object has properties like title, name, description which the user can edit and Save.
In the reducer Im using React.addons.update return new state object.
The main container view has 2 custom child components (wrapped in TabBarNavigator).
One of the child component has few TextInputs which is updating a state.
Using the logger middleware and console.log() I see the new state value in the parent view's render() (via this.props.name) but not in the child view.
I'm trying to figure out why the updated state is not propagated to the child container. Any suggestion is much appreciated.
Im at a point where Im thinking of subscribeing to the redux store manually in the child container but it feels wrong
my code looks like this:
MainView
Reducer
configure store etc
The MainView
const React = require('react-native');
const {
Component,
} = React;
const styles = require('./../Styles');
const MenuView = require('./MenuView');
import Drawer from 'react-native-drawer';
import TabBarNavigator from 'react-native-tabbar-navigator';
import BackButton from '../components/BackButton';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as PostActions from '../actions/Actions';
import {Details} from './Article/Details';
import {ArticleSecondary} from './Article/Secondary';
var update = require('react-addons-update');
import configureStore from '../store/configureStore';
class ArticleMainView extends Component {
constructor(props){
super(props);
//var store = configureStore(props.route.post);
this.state = {
};
}
componentDidMount(){
}
savePost() {
console.log(this.props.post.data);
this.props.navigator.pop();
}
render(){
console.log("ArticleMainView: render(): " + this.props.name);
return(
<TabBarNavigator
ref="navComponent"
navTintColor='#346293'
navBarTintColor='#94c1e8'
tabTintColor='#101820'
tabBarTintColor='#4090db'
onChange={(index)=>console.log(`selected index ${index}`)}>
<TabBarNavigator.Item title='ARTICLE' defaultTab>
<Details ref="articleDetail"
backButtonEvent={ () => {
this.props.navigator.pop();
}}
saveButtonEvent={ () => {
this.savePost();
}}
{...this.props}
/>
</TabBarNavigator.Item>
<TabBarNavigator.Item title='Secondary'>
<ArticleSecondary ref="articleSecondary"
{...this.props}
backButtonEvent={ () => {
this.props.navigator.pop();
}}
saveButtonEvent={ () => {
this.savePost();
}}
/>
</TabBarNavigator.Item>
</TabBarNavigator>
);
}
}
function mapStateToProps(state) {
return {
post: state,
text: state.data.text,
name: state.data.name,
description: state.data.description
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(PostActions, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(ArticleMainView);
The Reducer:
import {Constants} from '../api/Constants';
var update = require('react-addons-update');
export default function postReducer(state, action) {
switch(action.type) {
case Constants.SET_POST_TEXT:
if( state.data.text){
return update(state, {
data: { $merge: {text: action.text }}
});
}else{
return update(state, {
data: { $merge: {text: action.text }}
});
}
break;
case Constants.SET_POST_NAME:
return update(state, {
data: { name: { $set: action.text }}
});
return newO;
break;
case Constants.SET_POST_DESCRIPTION:
return update(state, {
data: { description: { $set: action.text }}
});
break;
default:
return state;
}
}
render scene of the app:
renderScene(route, navigator) {
switch (route.id) {
case "ArticleMainView":
let store = configureStore(route.post);
delete route.post; // TODO: not sure if I should remove this
return (
<Provider store={store}>
<ArticleMainView navigator={navigator} {...route}/>
</Provider>
);
default:
return <LandingView navigator={navigator} route={route}/>
}
}
configureStore:
import { createStore,applyMiddleware,compose } from 'redux'
import postReducer from '../reducers/SocialPostReducer';
import createLogger from 'redux-logger';
const logger = createLogger();
export default function configureStore(initialState){
return createStore(
postReducer,
initialState,
compose(applyMiddleware(logger))
);
}
If anyone stumbles on this question this is how I solved it. In each of the child components I declared a contextTypes object like so
ChildComponentView.contextTypes = {
store: React.PropTypes.object
}
to access the current state in the child component
let {store} = this.context;
store.getState();
I don’t know React Native well but something that threw me off is that you’re effectively creating a store on every render:
case "ArticleMainView":
let store = configureStore(route.post);
delete route.post; // TODO: not sure if I should remove this
return (
<Provider store={store}>
<ArticleMainView navigator={navigator} {...route}/>
</Provider>
);
Store should only be created once per application lifetime. It never makes sense to create it inside render() or renderScene() or similar methods. Please check the official Redux examples to see how the store is typically created.
Another problem is that you don’t show how you update the data, which child component doesn’t get updated, when you expect it to get updated, and so on. This is a lot of code, and it is very hard to help because it is incomplete, and most of it is not relevant to the problem. I would suggest you to remove all the irrelevant code until you can reproduce the problem with a minimal possible complete example. Then you can amend your question to include that example.