React native) where should i fetch data from server more faster? - mongodb

I'm beginner of react-native. I'm making music platform Application with my team.
I have a question. For example, when i search data in Screen1.
and i want to show related detailed data in Screen2.
but detailed data is stored in my db. so, i should async communication with my server.
But i don't know when i call function is better.
I make getData() function.
shortly example,
In Screen1
<TouchableOpacity onPress={() =>{getData(); navigate('Screen2');}} />
or
In Screen2
useEffect(() => {
getData();
,[]}
My App case is here
(Screen1)
<View>
<FlatList
numColumns ={2}
data={state.data}
keyExtractor={posts => posts.id}
onEndReached={onEndReached}
onEndReachedThreshold={0.8}
ListFooterComponent={loading && <ActivityIndicator />}
renderItem={({item}) =>{
return (
<View style ={{margin:'9%',}}>
<TouchableOpacity onPress={()=>{getCuration({isSong,object:item,id:item.id}); navigate('SelectedCuration', {id: item.id}); }}>
<View style={styles.post}>
<View style={{width:130, height:130}}>
<Imagetake url={item.attributes.artwork.url}></Imagetake>
</View>
<View>
<View>
<Text>{item.attributes.name.split("(feat.")[0]}</Text>
{ item.attributes.name.split("(feat.")[1] ?
<Text>feat. {item.attributes.name.split("(feat.")[1].slice(0,-1)}</Text> :
null}
<Text>{item.attributes.artistName}</Text>
</View>
</View>
</View>
</TouchableOpacity>
</View>
)
}}
/>
</View>
(Screen2)
import React, { useContext, useEffect, useState , Component} from 'react';
import { View, Text, Image, Button, StyleSheet,ActivityIndicator ,TextInput, SafeAreaView, TouchableOpacity, FlatList } from 'react-native';
import { Context as CurationContext } from '../../context/CurationContext';
import { Context as UserContext } from '../../context/UserContext';
import { Context as PlaylistContext } from '../../context/PlaylistContext';
import { Context as DJContext } from '../../context/DJContext';
import {Rating} from 'react-native-elements';
import { navigate } from '../../navigationRef';
import Modal from 'react-native-modal';
const Imagetake = ({url}) => {
url =url.replace('{w}', '500');
url = url.replace('{h}', '500');
return (
<Image style ={{borderRadius :10 , height:'100%', width:'100%'}} source ={{url:url}}/>
);
};
const SelectedCuration = ({navigation}) => {
const {state, postCuration, getmyCuration, deleteCuration, getCurationposts, likecurationpost,unlikecurationpost} = useContext(CurationContext);
const { state: userState, getMyCurating, getOtheruser } = useContext(UserContext);
const { getUserPlaylists } = useContext(PlaylistContext);
const { getSongs } = useContext(DJContext);
const [ispost, setIspost] = useState(false);
const [text, setText] = useState('');
const [showModal, setShowModal] = useState(false);
const [number, setNumber] = useState(0);
const curationid= navigation.getParam('id');
console.log('SelectedCuration Page');
const onClose =() => {
setShowModal(false);
}
return (
<SafeAreaView style={{flex:1}}>
{state.currentCuration.songorartistid == undefined || (state.currentCuration.songorartistid !=curationid) ? <ActivityIndicator/> :
<View style={{flex:1 , backgroundColor:'#fff'}}>
<View style={{flex:2.5}}>
<View style={{flex:2}}>
<View style={{flex:1 , flexDirection:'row'}}>
<View style= {{flex:3, justifyContent: 'center', alignItems:'center'}}>
<View style={{ borderRadius:50,width:100, height:100, backgroundColor:'#666', marginBottom:'10%'}}>
{state.currentCuration.isSong ? <Imagetake url={state.currentCuration.object.attributes.artwork.url}></Imagetake> : null}
</View>
<Text>{state.currentCuration.object.attributes.name}</Text>
</View>
<View style = {{flex:5, marginLeft:'10%',justifyContent:'center', alignItems:'flex-start'}}>
{state.currentCuration.participate.length==0
?
<Text style={{marginBottom:'5%'}}>별점 0</Text>
:
<Text style={{marginBottom:'5%'}}>별점 {(state.currentCuration.rating/state.currentCuration.participate.length).toFixed(2)}</Text>
}
<Text style={{marginBottom:'5%'}}>큐레이션에 참여한사람 {state.currentCuration.participate.length}</Text>
</View>
</View>
</View>
</View>
<View style={{flex:1.7}}>
{state.currentCuration.participate.includes(userState.myInfo._id) ?
<Button
title = "나의 큐레이션 보기"
color ='#E73177'
onPress ={() => {
setShowModal(true);
getmyCuration({id:state.currentCuration.songorartistid})
}}
/>
:
<View style={{flex:1.7}}>
{ispost ?
<View style={{flex:1.7}}>
<View style={{flex:2, justifyContent:'center', marginBottom:'5%', alignItems:'center'}}>
<TextInput
style={styles.inputBox}
value = {text}
onChangeText={text=>setText(text)}
placeholder="큐레이션 내용"
multiline={true}
autoCapitalize='none'
autoCorrect={false}
placeholderTextColor ="#888888"
keyboardType = "email-address"
/>
<Rating
type='heart'
ratingCount={5}
startingValue={0}
imageSize={30}
onFinishRating={(value)=>{setNumber(value);}}
/>
</View>
<View style={{flex:1, flexDirection:'row', justifyContent:'center'}}>
<Button
title = "큐레이션 작성"
color ='#E73177'
onPress ={() => {
postCuration({isSong:state.currentCuration.isSong , rating:number, object:state.currentCuration.object, textcontent:text, id:state.currentCuration.songorartistid})
getMyCurating();
setIspost(false);
setText('');
}}
/>
<Button
title = "큐레이션 취소"
color ='#E73177'
onPress ={() => {
setIspost(false);
setText('');
}}
/>
</View>
</View>
:
<Button
title = "큐레이션 작성하기"
color ='#E73177'
onPress ={() => {
setIspost(true);
}}
/>
}</View>
}
</View>
<View style={{flex:5}}>
<FlatList
data={state.currentCurationpost}
keyExtractor={comment => comment._id}
renderItem={({item}) =>{
return (
<View style={{flex:1}}>
<View style ={{flex:1, flexDirection:'row'}}>
<TouchableOpacity onPress={() => {
if(item.postUserId == userState.myInfo._id){
navigate('Account');
}else{
getUserPlaylists({id:item.postUserId});
getOtheruser({id:item.postUserId});
getSongs({id:item.postUserId});
getCurationposts({id: item.postUserId});
navigate('OtherAccount');
}}}>
<Text>작성자 {item.postuser}</Text>
</TouchableOpacity>
{ item.likes.includes(userState.myInfo._id) ?
<TouchableOpacity style={styles.end} onPress={()=>{ unlikecurationpost({id:item._id, songorartistid:item.songorartistid});}} >
<Text>♥︎</Text>
</TouchableOpacity> :
<TouchableOpacity style={styles.end} onPress={()=>{ likecurationpost({id:item._id, songorartistid:item.songorartistid});}}>
<Text>♡</Text>
</TouchableOpacity> }
<Text style>{item.likes.length}개</Text>
</View>
<View style ={{flex:2, flexDirection:'row'}}>
<Text>{item.textcontent}</Text>
</View>
{showModal ?
<Modal
isVisible={true}
onBackdropPress={onClose}
backdropOpacity={0.1}
style={{justifyContent:'flex-end', margin:0,}}>
<View style={{flex:0.5, backgroundColor:'#fff'}}>
{state.mycurationpost.likes == undefined ?
<ActivityIndicator/> :
<View>
<View>
<Text>작성자 {state.mycurationpost.postuser}</Text>
<Text>{state.mycurationpost.textcontent}</Text>
<Text>좋아요 {state.mycurationpost.likes.length}</Text>
</View>
<View style={{flexDirection:'row', justifyContent:'center'}}>
<Button
title = "큐레이션 지우기"
color ='#E73177'
onPress ={() => {
setShowModal(false);
deleteCuration({id:item._id})
getMyCurating();
}}
/>
</View>
</View>
}
</View>
</Modal>
:null
}
</View>
);
}}
/>
</View>
</View>
}
</SafeAreaView>
);
};
const styles = StyleSheet.create({
inputBox : {
borderWidth:0.8,
borderRadius:5,
borderColor : "#F4D726",
width:'80%',
height: '100%',
},
});
export default SelectedCuration ;
Curation Context is
import AsyncStorage from '#react-native-community/async-storage';
import createDataContext from './createDataContext';
import serverApi from '../api/serverApi';
import { navigate } from '../navigationRef';
const curationReducer = (state, action) => {
switch(action.type) {
case 'get_curation':
return { ...state, currentCuration: action.payload[0], currentCurationpost:action.payload[1] };
case 'get_curationposts':
return { ...state, curationposts:action.payload };
case 'init_curationposts':
return { ...state, curationposts:action.payload };
case 'get_mycuration':
return { ...state, mycurationpost:action.payload };
case 'post_curation':
return { ...state, currentCuration: action.payload[0], currentCurationpost: [...state.currentCurationpost, action.payload[1]] };
case 'like_curationpost':
return { ...state, currentCuration: action.payload[0], currentCurationpost:action.payload[1] };
default:
return state;
}
};
const postCuration = dispatch => {
return async ({ isSong, object, textcontent, id, rating }) => {
try {
const response = await serverApi.post('/curationpost/'+id, { isSong, object, textcontent, rating });
dispatch({ type: 'post_curation', payload: response.data });
}
catch(err){
dispatch({ type: 'error', payload: 'Something went wrong with postCuration' });
}
}
};
const deleteCuration = dispatch => {
return async ({id}) => {
try {
const response = await serverApi.delete('/curationpost/'+id);
dispatch({ type: 'get_curation', payload: response.data });
}
catch(err){
dispatch({ type: 'error', payload: 'Something went wrong with deleteCuration' });
}
}
};
const likecurationpost = dispatch => {
return async ({id, songorartistid}) => {
try {
const response = await serverApi.post('/curationpostlike/'+id+'/'+songorartistid);
dispatch({ type: 'like_curationpost', payload: response.data });
}
catch(err){
dispatch({ type: 'error', payload: 'Something went wrong with likecurationpost' });
}
}
};
const unlikecurationpost = dispatch => {
return async ({id, songorartistid}) => {
try {
const response = await serverApi.delete('/curationpostlike/'+id+'/'+songorartistid);
dispatch({ type: 'like_curationpost', payload: response.data });
}
catch(err){
dispatch({ type: 'error', payload: 'Something went wrong with unlikecurationpost' });
}
}
};
const initcurationposts = dispatch => {
return async () => {
try {
dispatch({ type: 'init_curationposts', payload: null });
}
catch(err){
dispatch({ type: 'error', payload: 'Something went wrong with initcurationposts' });
}
}
};
const getCuration = dispatch => {
return async ({isSong,object,id}) => {
try {
const response = await serverApi.post('/curation/'+id, {isSong,object});
dispatch({ type: 'get_curation', payload: response.data });
}
catch(err){
dispatch({ type: 'error', payload: 'Something went wrong with getCuration' });
}
}
};
const getCurationposts = dispatch => {
return async ({ id }) => {
try {
const response = await serverApi.get('/curationposts/'+id);
dispatch({ type: 'get_curationposts', payload: response.data });
}
catch(err){
dispatch({ type: 'error', payload: 'Something went wrong with getCurationposts' });
}
}
};
const getmyCuration = dispatch => {
return async ({ id }) => {
try {
const response = await serverApi.get('/mycurationpost/'+id);
dispatch({ type: 'get_mycuration', payload: response.data });
}
catch(err){
dispatch({ type: 'error', payload: 'Something went wrong with getmyCuration' });
}
}
};
export const { Provider, Context } = createDataContext(
curationReducer,
{ postCuration, deleteCuration, likecurationpost,unlikecurationpost,
initcurationposts, getCuration, getCurationposts, getmyCuration },
{ currentCuration:{}, currentCurationpost:[], mycurationpost:{}, curationposts:null, errorMessage: ''}
)
Curation Routes in Server
const express = require('express');
const mongoose = require('mongoose');
const Curation = mongoose.model('Curation');
const Curationpost = mongoose.model('CurationPost');
const User = mongoose.model('User');
const Notice = mongoose.model('Notice');
const requireAuth = require('../middlewares/requireAuth');
var admin = require('firebase-admin');
const router = express.Router();
require('date-utils');
router.use(requireAuth);
router.get('/user', async(req, res) => {
const user= await User.findOne({email : req.user.email});
res.send(user);
});
//post Curation
router.post('/curationpost/:id', requireAuth, async (req, res) =>{
const { isSong, object, textcontent, rating } = req.body;
var newDate = new Date()
var time = newDate.toFormat('YYYY-MM-DD HH24:MI:SS');
try {
const curationpost = new Curationpost({ isSong, object, rating, postUser: req.user.name, postUserId: req.user._id, time, textcontent, songorartistid:req.params.id });
await curationpost.save();
const curation = await Curation.findOneAndUpdate({ songorartistid:req.params.id }, {$push: { participate:req.user._id }, $inc : { rating:rating }}, {new:true});
res.send([curation, curationpost]);
} catch (err) {
return res.status(422).send(err.message);
}
});
// delete Curation
router.delete('/curationpost/:id', async (req, res) =>{
try {
const curationpost = await Curationpost.findOneAndDelete({_id:req.params.id});
const curationposts = await Curationpost.find({songorartistid:curationpost.songorartistid});
const curation = await Curation.findOneAndUpdate({songorartistid:curationpost.songorartistid},{$pull:{participate:curationpost.postUserId}, $inc:{rating:-1*curationpost.rating}}, {new:true});
res.send([curation, curationposts]);
} catch (err) {
return res.status(422).send(err.message);
}
});
// like Curation post
router.post('/curationpostlike/:id/:songorartistid', requireAuth, async(req,res) =>{
var newDate = new Date()
var noticeTime = newDate.toFormat('YYYY-MM-DD HH24:MI:SS');
try{
const curation = await Curation.findOne({songorartistid:req.params.songorartistid});
const curationpost = await Curationpost.findOneAndUpdate({_id : req.params.id}, {$push : {likes : req.user._id}}, {new:true});
const curationposts = await Curationpost.find({songorartistid:req.params.songorartistid});
if(curationpost.postUserId.toString() != req.user._id.toString()){
try {
const notice = new Notice({ noticinguser:req.user._id, noticieduser:curationpost.postUserId, noticetype:'culike', time: noticeTime, curationpost:curationpost._id });
await notice.save();
} catch (err) {
return res.status(422).send(err.message);
}
}
res.send([curation, curationposts]);
const targetuser = await User.findOne({_id:curationpost.postUserId});
if( targetuser.noticetoken != null && targetuser._id.toString() != req.user._id.toString()){
var message = {
notification : {
title: curation.object.attributes.artistName + ' - ' + curation.object.attributes.name,
body : req.user.name + '님이 큐레이션을 좋아합니다.',
},
token : targetuser.noticetoken
};
try {
await admin.messaging().send(message).then((response)=> {}).catch((error)=>{console.log(error);});
} catch (err) {
return res.status(422).send(err.message);
}
}
}catch(err){
return res.status(422).send(err.message);
}
});
// unlike Curation post
router.delete('/curationpostlike/:id/:songorartistid', requireAuth, async(req,res) =>{
try{
const curation = await Curation.findOne({songorartistid:req.params.songorartistid});
const curationpost = await Curationpost.findOneAndUpdate({_id : req.params.id}, {$pull : {likes : req.user._id}}, {new:true});
const curationposts = await Curationpost.find({songorartistid:req.params.songorartistid});
await Notice.findOneAndDelete({$and: [{ curation:curation._id }, { curationpost:curationpost._id }, { noticinguser:req.user._id }, { noticetype:'culike' }, { noticieduser:curationpost.postUserId }]});
res.send([curation, curationposts]);
}catch(err){
return res.status(422).send(err.message);
}
});
// getCuration
router.post('/curation/:id', async (req, res) =>{
const { isSong, object } = req.body;
try {
const check = await Curation.findOne({songorartistid:req.params.id});
if (check == null){
const curation = new Curation({isSong, object, songorartistid:req.params.id});
await curation.save();
const curationpost = await Curationpost.find({songorartistid:req.params.id});
res.send([curation,curationpost]);
}else {
const curationpost = await Curationpost.find({songorartistid:req.params.id});
res.send([check,curationpost]);
}
} catch (err) {
return res.status(422).send(err.message);
}
});
// get user curationposts
router.get('/curationposts/:id', async (req, res) =>{
try {
const curationpost = await Curationpost.find({postUserId:req.params.id});
res.send(curationpost);
} catch (err) {
return res.status(422).send(err.message);
}
});
// get MyCuration
router.get('/mycurationpost/:id/', requireAuth, async (req, res) =>{
try {
const curationpost = await Curationpost.findOne({$and :[{ songorartistid: req.params.id }, { postUserId: req.user._id }]});
res.send(curationpost);
} catch (err) {
return res.status(422).send(err.message);
}
});
module.exports = router;
So, My app is still waiting when state.currentContent gets.
getCuration() is function to get state.currentContent.
So My Question is
put getData() func in Screen1 when navigate screen2
put getData() func in Screen2 useEffect
problem is getData(in this case getCuration) is Context function(useContext) ??
So, in first solution, when i go to screen2, screen1 is re rendering.
in second solution, getData() is little later than solution 1. So, data is loading longer when people feel i think.
which is better?? help me plz...

There are some solutions that can help you access this state fast
The trick is to make it global and then access them wherever you are in your entire app. You will just make a request from your main screen and check if the state changes or not, so if Screen1 is the first to be displayed in your app, just put this logic inside.
You can
use AsynchStorage: which is asynchronous encrypted but I think a bit complex than
use useGlobal: it's synchronous in term of speediness to access data it's the best one
Use Redux: more complex if your app is not so big
Find the documentation here
https://www.npmjs.com/package/reactn
https://github.com/react-native-async-storage/async-storage
https://code.tutsplus.com/tutorials/using-redux-in-a-react-native-app--cms-36001

Related

may i use this code for finduserDetail in react using redux-thunk dispatch to calling function

This code for finduserdetail by hitting function with help of dispatch method and passing (match.params.id) not working, even function not called as I know on dispatch method it should be called how may I call this so that our stat could be update in root.js file then I can show detail on my ui by using useselector
in productDetail.js
import { Fragment } from "react";
import Carousel from "react-material-ui-carousel";
import {useParams} from "react-router-dom";
import './ProductDetails.css';
import {useDispatch} from "react-redux";
import { useEffect } from "react";
import { getProductDetail } from "../../actions/productAction";
const ProductDetails = () =>{
console.log("hello this is detail")
const dispatch= useDispatch();
let params = useParams()
const id= params.id;
// const {product,error} = useSelector(
// (state) =>state.product)
useEffect(()=>{
dispatch(getProductDetail(id))
}, [dispatch, id])
return(
<Fragment>
<div className="ProductDetails">
<div>
<Carousel>
{/* {product.images &&
product.images.map((item,i)=>{
<img
className="CarouselImage"
key={item.url}
src={item.url}
alt={`${i} Slide`}
/>
})} */}
</Carousel>
</div>
</div>
</Fragment>
);
};
export default ProductDetails
and using for calling api for findproductDetail using getProductDetail in productAction.js
export const getProductDetail =(id) => async (dispatch) => {
try {
dispatch({ type: PRODUCT_DETAILES_REQUEST });
const { data } = await axios.get(`/api/v1/product/${id}`);
dispatch({
type: PRODUCT_DETAILES_SUCCESS,
payload: data,
});
} catch (error) {
dispatch({
type: PRODUCT_DETAILES_FAIL,
payload: error.response.data.message,
});
}
};
and one other file productReducer.js
export const productDetailsReducer = (state = { product: {} }, action) => {
switch (action.type) {
case PRODUCT_DETAILES_REQUEST:
return {
loading: true,
...state,
};
case PRODUCT_DETAILES_SUCCESS:
return {
loading: false,
product: action.payload.product,
};
case PRODUCT_DETAILES_FAIL:
return {
loading: false,
error: action.payload,
};
and another file store.js
import { legacy_createStore as createStore, combineReducers, applyMiddleware } from 'redux';
import thunk from "redux-thunk";
import { composeWithDevTools } from "redux-devtools-extension";
import { productDetailsReducer, productReducer } from './reducers/productReducer';
const reducer = combineReducers({
products: productReducer,
product: productDetailsReducer,
});
let initialState ={};
const middleware = [thunk];
const store = createStore(reducer, initialState,
composeWithDevTools(applyMiddleware(...middleware))
);
export default store;
These stuff not working. I am quite beginner in React programming
import { Fragment } from "react";
import Carousel from "react-material-ui-carousel";
import {useParams} from "react-router-dom";
import './ProductDetails.css';
import {useDispatch} from "react-redux";
import { useEffect } from "react";
import { getProductDetail } from "../../actions/productAction";
const ProductDetails = () =>{
console.log("hello this is detail")
const dispatch= useDispatch();
let params = useParams()
const id= params.id;
// const {product,error} = useSelector(
// (state) =>state.product)
useEffect(()=>{
dispatch(getProductDetail(id))
}, [dispatch, id])
return(
<Fragment>
<div className="ProductDetails">
<div>
<Carousel>
{/* {product.images &&
product.images.map((item,i)=>{
<img
className="CarouselImage"
key={item.url}
src={item.url}
alt={`${i} Slide`}
/>
})} */}
</Carousel>
</div>
</div>
</Fragment>
);
};
export default ProductDetails
and using for calling api for findproductDetail using getProductDetail in productAction.js
export const getProductDetail =(id) => async (dispatch) => {
try {
dispatch({ type: PRODUCT_DETAILES_REQUEST });
const { data } = await axios.get(`/api/v1/product/${id}`);
dispatch({
type: PRODUCT_DETAILES_SUCCESS,
payload: data,
});
} catch (error) {
dispatch({
type: PRODUCT_DETAILES_FAIL,
payload: error.response.data.message,
});
}
};
and one other file productReducer.js
export const productDetailsReducer = (state = { product: {} }, action) => {
switch (action.type) {
case PRODUCT_DETAILES_REQUEST:
return {
loading: true,
...state,
};
case PRODUCT_DETAILES_SUCCESS:
return {
loading: false,
product: action.payload.product,
};
case PRODUCT_DETAILES_FAIL:
return {
loading: false,
error: action.payload,
};
and another file store.js
import { legacy_createStore as createStore, combineReducers, applyMiddleware } from 'redux';
import thunk from "redux-thunk";
import { composeWithDevTools } from "redux-devtools-extension";
import { productDetailsReducer, productReducer } from './reducers/productReducer';
const reducer = combineReducers({
products: productReducer,
product: productDetailsReducer,
});
let initialState ={};
const middleware = [thunk];
const store = createStore(reducer, initialState,
composeWithDevTools(applyMiddleware(...middleware))
);
export default store;
The most important stuff my redux state is not updating because of id matching condition once if
state will get update I am checking using redux tool

Nexjs + SWR: API resolved without sending a response for /api/projects/<slug>, this may result in stalled requests

Since on first render I was not able to get the router.query I am passing the params from getServerSideProps as follows:
export async function getServerSideProps(context) {
return {
props: { params: context.params },
};
}
Then in the function am trying to do the API call but am getting the API stalled error
API resolved without sending a response for
/api/projects/nichole_robel23, this may result in stalled requests.
This is my code:
export default function Project({ params }) {
const { slug } = params;
let [projectData, setProjectData] = useState([]);
let [loading, setLoading] = useState(true);
const { data } = useSWR('http://localhost:3000/api/projects/' + slug);
useEffect(() => {
if (data) {
setProjectData(data.data.project);
setLoading(false);
}
}, [data]);
......
I have global SWRCofig as follows
<SWRConfig value={{ fetcher: (url) => axios(url).then(r => r.data) }}>
<Layout>
<Component {...pageProps} />
</Layout>
</SWRConfig>
Any way to solve the problem?
You are missing your fetcher–the function that accepts the key of SWR and returns the data, so the API is not being called.
You are also not returning a response correctly from the API–this is most likely a case of not waiting for a promise/async to be fulfilled correctly.
CLIENT
const fetcher = (...args) => fetch(...args).then((res) => res.json());
export default function Home({ params }) {
const { slug } = params;
const [projectData, setProjectData] = useState([]);
const [loading, setLoading] = useState(true);
const { data } = useSWR(`http://localhost:3000/api/projects/${slug}`, fetcher);
useEffect(() => {
if (data) {
setProjectData(data);
setLoading(false);
}
}, [data]);
API
const getData = () => {
return new Promise((resolve, reject) => {
// simulate delay
setTimeout(() => {
return resolve([{ name: 'luke' }, { name: 'darth' }]);
}, 2000);
});
}
export default async (req, res) => {
// below will result in: API resolved without sending a response for /api/projects/vader, this may result in stalled requests
// getData()
// .then((data) => {
// res.status(200).json(data);
// });
// better
const data = await getData();
res.status(200).json(data);
}

How to resolve Error " Too many re-renders. React limits the number of renders to prevent an infinite loop." in react native?

I have develop form to submit complaint by selecting product prom picker. So I externally implement the picker and then use it in complaint submission form. For that I was needed to take selectedValue state into complaint submission form by using function handle change. After i implement that faction and change appropriate places regarding to the tutorial link : [https://github.com/reactjs/reactjs.org/issues/1689][1]
But when I navigate to the complaint submission form it says the error as " Error: Too many re-renders. React limits the number of renders to prevent an infinite loop."So help me to resove and please confirm am I follow the above tutorial correctly.
Complaint submission form:
import * as React from 'react';
import {Button, View, Text, ScrollView, StyleSheet, Alert} from 'react-native';
import {Appbar} from 'react-native-paper';
import {TextInput, HelperText} from 'react-native-paper';
import {useEffect, useState} from 'react';
import AsyncStorage from '#react-native-community/async-storage';
import ProductPicker from './ProductPicker';
const ComplaintSubmission = ({navigation}) => {
const [productID , setproductID] = useState('');
const [description , setdescription] = useState('');
const [token, setToken] = useState('');
useEffect(() => {
saveToken();
}, []);
function handleChange(newValue){
setproductID(newValue);
}
const saveToken = async () => {
const token = await AsyncStorage.getItem('userToken');
console.log('token from storage', token);
setToken(token);
}
const send = () =>{
fetch("http://10.0.2.2:3000/customer/lodge-complaint", {
method: "post",
headers: {
'Content-Type': 'application/json',
'Authentication': `Bearer ${token}`
},
body: JSON.stringify({
description : description,
productID : value
})
})
}
const openAlert = () => {
Alert.alert(
"Complaint Successfully Submitted",
"We review it as soon as possible. Thank you for reaching for us!",
[{
text: "OK",
onPress : () => navigation.navigate("DashboardDrawer" ),
}]
);
}
return (
<ScrollView>
<Appbar.Header>
<Appbar.BackAction onPress={() => navigation.goBack()} />
<Appbar.Content title="Submit Complaint" />
<Appbar.Action icon="magnify" onPress={() => navigation.openDrawer()} />
</Appbar.Header>
<Text>Plese Fill the following</Text>
<View>
{/*{console.log('renderer token', token)}*/}
<ProductPicker value={productID} onValueChange = {handleChange()} />
<HelperText type="info">
Make sure select the correct Product
</HelperText>
</View>
<TextInput
style={styles.PIDstyle}
label="Description"
onChangeText = {(description) => setdescription(description)}
/>
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Text>This is submittion</Text>
<Button onPress={() => {send(); openAlert();}} title="Submit Complaint" />
</View>
</ScrollView>
);
};
export default ComplaintSubmission;
const styles = StyleSheet.create({
PIDstyle: {
marginTop: 30,
marginLeft: 10,
marginRight: 10,
},
});
And this is the picker component:
import React, {useEffect, useState} from 'react';
import {View, StyleSheet} from 'react-native';
import {Picker} from '#react-native-picker/picker';
import AsyncStorage from '#react-native-community/async-storage';
const ProductPicker = () => {
const [selectedValue, setSelectedValue] = useState('');
const [productDetails, setproductDetails] = useState([]);
console.log('product id---', selectedValue);
useEffect(() => {
getProductList();
}, []);
function handleChange(event){
props.onValueChange(event.target.value);
}
const getProductList = async () => {
const token = await AsyncStorage.getItem('userToken');
console.log(' function eka athule------', token);
fetch('http://10.0.2.2:3000/customer/get-all-products', {
method: 'post',
headers: {
'Content-Type': 'application/json',
'Authentication': `Bearer ${token}`,
},
})
.then((response) => response.json())
.then((json) => setproductDetails(json.data))
.catch((error) => console.error(error));
};
return (
<View style={styles.container}>
<Picker
selectedValue={selectedValue}
style={{height: 40, width: 150}}
onValueChange={(itemValue, itemIndex) => {
setSelectedValue(itemValue);
handleChange();
}}
>
{productDetails.map((item, index) => {
return (
<Picker.Item label={item.productName} value={props.item.productID} key={index}/>);
})}
</Picker>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 40,
alignItems: 'center',
},
});
export default ProductPicker;
Why don't you pass the itemValue to handleChange?
onValueChange={(itemValue, itemIndex) => {
setSelectedValue(itemValue);
handleChange(itemValue);
}}
Then change the function:
function handleChange(value){
props.onValueChange(value);
}

How can I render fetched information from a REST API in React Native?

I'm developing a screen which fetches Spotify playlists of a particular category, and prints the playlist information (and then allows the user to play them). I'm currently just trying to print the names of the playlists, but I'm getting an error. The playlists are being fetched just fine, as I can see in my console, though I'm struggling to render those details onto the screen.
This is my code:
import React, { Component } from 'react'
import { StyleSheet, SafeAreaView, ActivityIndicator, View, Text, Image} from 'react-native';
import * as Font from 'expo-font';
import styled from 'styled-components';
import { Ionicons } from '#expo/vector-icons';
import dimensions from '../components/ScreenSize';
import colours from '../components/Colours';
import { Audio } from 'expo-av';
import { FlatList, TouchableHighlight } from 'react-native-gesture-handler';
const client_id = {Client_ID}
const client_secret = {Client_Secret}
const item = ({item}) => (
<View>
<TouchableHighlight onPress={() => this.fetchTracks(item.id)}>
<View>
<Text {{uri:item.name}}/>
</View>
</TouchableHighlight>
</View>
)
export default class HomeScreen extends React.Component {
state={
fontsLoaded:false,
}
async componentDidMount() {
await Font.loadAsync({
'montserrat-regular': require('../assets/fonts/Montserrat/Montserrat-Regular.ttf'),
'montserrat-light': require('../assets/fonts/Montserrat/Montserrat-Light.ttf'),
'montserrat-semibold': require('../assets/fonts/Montserrat/Montserrat-SemiBold.ttf'),
'montserrat-bold': require('../assets/fonts/Montserrat/Montserrat-Bold.ttf'),
}
).then(() => this.setState({ fontsLoaded:true}))
this.getToken();
this.setAudio();
}
constructor (props) {
super(props)
this.playbackInstance=null;
this.state = {
playing:false,
token: '',
DATA:[],
};
}
setAudio=() => {
Audio.setAudioModeAsync({
allowsRecordingIOS:false,
interruptionModeIOS: Audio.INTERRUPTION_MODE_IOS_DO_NOT_MIX,
playsInSilentModeIOS: true,
shouldDuckAndroid: true,
interruptionModeAndroid: Audio.INTERRUPTION_MODE_ANDROID_DO_NOT_MIX,
playThroughEarpieceAndroid: false,
});
}
componentDidCatch(error, info)
{
console.log(error, info.componentStack);
}
getToken = async() =>
{
try
{
const getspotifytoken = await fetch("https://accounts.spotify.com/api/token",
{
method:'POST',
body: `grant_type=client_credentials&client_id=${client_id}&client_secret=${client_secret}`,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
const spotifytoken = await getspotifytoken.json();
this.setState({
token: spotifytoken.access_token
});
console.log(this.state.token);
}
catch(err)
{
console.log("Error fetching data ", err);
}
}
search = async () => {
try
{
const query = "mood"
console.log('Searching: ', query)
const spotifyApiCall = await fetch(`https://api.spotify.com/v1/browse/categories/${query}/playlists?`, {
headers: {
Accept: 'application/json',
Authorization: `Bearer ${this.state.token}`,
"Content-Type":'application/json'
}
})
const spotify = await spotifyApiCall.json();
console.log("Items ", spotify);
this.setState({
DATA: spotify.playlists.items,
})
}
catch (err)
{
console.log("Error fetching data ", err);
}
}
fetchTracks = async (playlistId) => {
console.log('Playlist ', playlistId)
try
{
const getplaylist = await fetch(`https://api.spotify.com/v1.playlist/${playlistId}`,
{
method:'GET',
headers: {
Accept:"application/json",
Authorization:`Bearer ${this.state.token}`,
"Content-Type":"application/json"
}
});
const playlist = await getplaylist.json();
console.log('music ', playlist.tracks.items[0].preview_url);
}
catch (err)
{
console.log("Error fetching data ", err);
}
}
async _loadNewPlaybackInstance(playing, track) {
if(this.playbackInstance != null)
{
await this.playbackInstance.unloadAsync();
this.playbackInstance.setOnPlaybackStatusUpdate(null);
this.playbackInstance = null;
}
const source = {uri: track};
const initialStatus = {
shouldPlay: true,
rate: 1.0,
shouldCorrectPitch: true,
volume: 1.0,
isMuted: false
};
const {sound, status} = await Audio.Sound.createAsync(
source.initialStatus);
this.playbackInstance=sound;
this.playbackInstance.setIsLoopingAsync(false);
this.playbackInstance.playAsync();
if (this.state.selected === playlistId) {
console.log("Playing, so stop");
this.setState({selected:null});
this.playbackInstance.pauseAsync();
return;
}
this.setState({ selected:playlistId});
this._loadNewPlaybackInstance(true, playlist.tracks.items[0].preview_url);
}
render() {
if(!this.state.fontsLoaded ) {
return null
}
return (
<Container>
<Titlebar>
<Title>Music</Title>
</Titlebar>
<HeaderBar2>
<TouchableHighlight onPress={() => this.search()}>
<Header2>Playlists for your Mood</Header2>
</TouchableHighlight>
</HeaderBar2>
<View>
<FlatList
data = {this.state.DATA}
renderItem={item}
keyExtractor = {item.id}
numColumns={2}
extraData = {this.state}
/>
</View>
</Container>
);
}
}
And the error is: Unexpected token, expected '...' (18:23)
which is in reference to the line which reads <Text {{uri:item.name}}/>
I've also tried <Text {{item.name}}/>, as well as a few other alternatives, but I can't quite figure it out.
Thank you for reading, I'd really appreciate any help!
The thing you are doing wrong is you can not use Text like you are using above, check with this:
replace
<Text {{uri:item.name}}/>
to
<Text>{item.name}</Text>
Hope this helps!

fetching data from api and shows on Render Method

I am fetched data from api but the problem is
when i am show data in render method then it showing "Undefine"
Please Help me to fix it
This is my code:-
var ProductData=''
export default class ApiProduct extends Component {
FetchProduct=()=>{
fetch('https://drawtopic.in/projects/wordpress/wp- json/wc/v2/products?consumer_key=ck_044491712632ef889ec13c75daff5879a8291674&consumer_secret=cs_a8e16c732e1812017e15d278e1dce2765a88c49b',{
method:'GET',
})
.then((response) => response.json())
.then((res) =>{
ProductData= res;
})
}
render() {
{this.FetchProduct()}
{console.warn(ProductData)}
return (
<View/>
)}
i Want to Show All data in render method
Here is a quick Expo example that should show you how to render a simple list. It is not a good idea to call fetch inside the render method, as every re-render will call the fetch.
Here is an expo snack https://snack.expo.io/S1-LKIyQE
import React from 'react';
import { Text, View, StyleSheet, FlatList, SafeAreaView } from 'react-native';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
productData: []
}
}
async componentDidMount () {
await this.getData();
}
async getData() {
try {
let url ='https://drawtopic.in/projects/wordpress/wp-json/wc/v2/products?consumer_key=ck_044491712632ef889ec13c75daff5879a8291674&consumer_secret=cs_a8e16c732e1812017e15d278e1dce2765a88c49b'
let response = await fetch(url, { method:'GET' });
let responseJson = await response.json();
this.setState({productData: responseJson});
} catch (err) {
console.warn(err);
}
}
renderItem = ({item}) => {
return (
<View style={styles.mainItem}>
<Text>{item.name}</Text>
</View>
);
}
keyExtractor = (item, index) => {
return index.toString();
}
render() {
return (
<SafeAreaView style={styles.container}>
<FlatList
extraData={this.state}
data={this.state.productData}
keyExtractor={this.keyExtractor}
renderItem={this.renderItem}
/>
</SafeAreaView>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white'
},
mainItem: {
width:200,
height: 80,
justifyContent: 'center',
alignItems: 'center',
margin: 10,
backgroundColor: 'yellow',
borderColor: 'black',
borderWidth: 1
},
});
Here I have used async/await as it can make for much cleaner and clearer code. This is a great article on the differences between promises and async/await https://medium.com/#bluepnume/learn-about-promises-before-you-start-using-async-await-eb148164a9c8.
I have also given you a quick example on how to use a FlatList to display your data. You should check the docs on how to use it properly https://facebook.github.io/react-native/docs/flatlist
If you want to edit how each item is displayed on the screen then you need to update the renderItem method.
Try this way, if you have a question of how it works makes me to know.
let self;
export default class ApiProduct extends Component {
constructor(){
super();
self = this;
this.state = {
productData: null;
};
}
FetchProduct=()=>{
fetch('https://drawtopic.in/projects/wordpress/wp- json/wc/v2/products?consumer_key=ck_044491712632ef889ec13c75daff5879a8291674&consumer_secret=cs_a8e16c732e1812017e15d278e1dce2765a88c49b',{
method:'GET',
})
.then((response) => response.json())
.then((res) =>{
self.setState({ productData: res});
});
}
render() {
this.FetchProduct();
console.warn(self.state.productData);
return (
<View/>
);
}
I'll try to make order in your code.
Fetching data in the render method is not a good idea, it's better to use lifecycle methods, like componentDidMount. In order to handle your request result, set a state field and in your render read data from that field. So:
export default class ApiProduct extends Component {
constructor(){
super();
this.state = {
productData: undefined;
};
}
async componentDidMount(){
await this.fetchProduct();
}
fetchProduct = () => {
fetch('https://drawtopic.in/projects/wordpress/wp- json/wc/v2/products?consumer_key=ck_044491712632ef889ec13c75daff5879a8291674&consumer_secret=cs_a8e16c732e1812017e15d278e1dce2765a88c49b',{
method:'GET',
})
.then((response) => response.json())
.then((res) =>{
this.setState({
productData: res
})
})
}
render() {
const {productData} = this.state;
console.log(productData);
return (
<View/> // add here your code to render data properly
)
}}