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

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

Related

How to inject $axios into Pinia store SSR

I'm trying to inject my axios instance into the store so that I'm able to login into the app but unfortunately I'm being unable to. I have the followed boot file
import { boot } from 'quasar/wrappers';
import axios from 'axios';
import type {AxiosResponse} from 'axios';
import type { StatusCodes } from 'http-status-codes';
export type WrappedResponse = { response?: AxiosResponse };
export const isError = (e: WrappedResponse, statusCode: StatusCodes) =>
e.response && e.response.status === statusCode;
export default boot(({ app, store }) => {
const api = axios.create({ baseURL: import.meta.env.VITE_APP_API_BASE_URL });
app.provide('axios', api);
store.$axios = api;
});
Then on my store I have:
import { defineStore } from 'pinia';
export const useAppStore = defineStore('app', {
state: () => ({
}),
getters: {
},
actions: {
async login() {
console.log(this.$axios);
console.log('Logging in from store');
}
},
});
Whenever login is called it prints undefined. Any idea on what I'm doing wrong?
You simply have to create a Pinia plugin:
export default boot(({ app, store }) => {
const api = axios.create({ baseURL: import.meta.env.VITE_APP_API_BASE_URL });
app.provide('axios', api);
store.use(() => ({ api })); // πŸ‘ˆ
});

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

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

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
)
}}

How to test axios interceptors using jest?

I'm trying to test the following code:
import axios from 'axios';
import { history } from './ReduxService';
axios.interceptors.response.use(response => response,
(error) => {
if ((error.response && error.response.status === 408) || error.code === 'ECONNABORTED') {
history.push('/error');
}
return Promise.reject(error);
}
);
Any advice on how to cover it?
First, modify the code so that you can pass a mocked version of axios in:
import axios, { AxiosInstance } from 'axios';
import { history } from './ReduxService';
export const addResponseInterceptor(client: AxiosInstance) => {
client.interceptors.response.use(response => response,
(error) => {
if ((error.response && error.response.status === 408) || error.code ===
'ECONNABORTED') {
history.push('/error');
}
return Promise.reject(error);
});
};
Then set up your tests like this:
import { addResponseInterceptor } from './yourInterceptorFile'
import axios from 'axios';
jest.mock('axios', () => {
return {
create: jest.fn(),
interceptors: {
request: {
use: jest.fn(),
eject: jest.fn(),
},
response: {
use: jest.fn(),
eject: jest.fn(),
},
}
};
});
describe('addResponseInterceptor tests', () => {
beforeEach(() => {
(axios.create as jest.Mock).mockReset();
(axios.interceptors.request.use as jest.Mock).mockReset();
(axios.interceptors.request.eject as jest.Mock).mockReset();
(axios.interceptors.response.use as jest.Mock).mockReset();
(axios.interceptors.response.eject as jest.Mock).mockReset();
});
it('should add a response interceptor to the axios instance', () => {
addResponseInterceptor(axios);
expect(axios.interceptors.response.use).toHaveBeenCalled();
});
it('should push to history when an error occurs', async() => {
const historySpy = jest.spyOn(history, 'push');
const axiosClient = axios;
addResponseInterceptor(axios);
const interceptorErrorHandler = (axiosClient.interceptors.response.use as jest.Mock).mock.calls[0][1];
try {
await interceptorErrorHandler({
response: {
status: 408
}
});
//this should not be called--the promise should be rejected
expect(true).toBe(false);
} catch {
expect(historySpy).toHaveBeenCalledWith('/error');
}
});
. . .
});