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
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
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!
I am new to React hooks/Context API. I have read the React hook/context docs, and I am still having trouble with the following:
My attempts to update global state by multiple consumer components
currently causes frequent overwriting of context state due to
rerendering (e.g., activity or details state is sometimes
null/undefined). This probably is why...
... I am getting 400 (bad request) and/or 500 (server) errors on random refreshes of the page (~30% of the time content loads as
expected, ~70% errors are thrown. I believe this is happening
because we have various context states that are being called
asynchronously).
I am not sure how to implement Axios Cancellation, given that our useEffect hooks are calling dispatch functions (e.g.,
getActivities()) in different files. The examples I've seen
involve fetching data within the component (rather than in context).
I am seeking assistance for #1 specifically. I would love guidance on how to accurately fetch data and store in context as global state, and then provide that context to child components, allowing them to consume/update context state without unnecessary rerendering.
Tried to only provide relevant code snippets below:
ActivityState.js -- should fetch activity data
...
const ActivityState = props => {
const initialState = {
activities: [],
isLoading: false,
isError: false
};
const HEADERS = {
'Content-Type': 'application/json',
'user_id': 1
}
const [state, dispatch] = useReducer(ActivityReducer, initialState);
const userContext = useContext(UserContext);
const getActivities = async () => {
const { loggedIn } = contactContext;
let didCancel = false; // attempts to start implementing axios cancellation
try {
const res = await axios.get(url);
dispatch({ type: GET_ACTIVITIES, payload: res.data.data.activities });
} catch (err) {
if (!didCancel) {
dispatch({ type: 'FETCH_FAILURE' });
}
}
}
const updateActivity = (path, data) => { //update context state
dispatch({ type: UPDATE_ACTIVITY, payload: { path: path, data: data } });
};
const saveActivity = () => { //send new activity data to the backend
const postData = {
actions: [{"293939": []}],
activities: state.activities
};
try {
const res = axios.post(url,{ data: postData }, { headers: HEADERS });
} catch (err) {
console.log(err);
}
}
return (
<ActivityContext.Provider
value={{
activities: state.activities,
data: state.data,
backup_data: state.backup_data,
getActivities,
updateActivity,
saveActivity,
}}
>
{props.children}
</ActivityContext.Provider>
);
};
export default ActivityState;
ActivityReducer.js -- switch statements to be dispatched by ActivityState.js
...
export default (state, action) => {
switch (action.type) {
case GET_ACTIVITIES:
return {
...state,
activities: action.payload,
isLoading: true
};
case FETCH_FAILURE:
return {
...state,
isLoading: false,
isError: true
};
case UPDATE_ACTIVITY:
const { payload: { path }, payload } = action;
const data = state;
if (!data.activities)
return { data };
const index = data.activities.findIndex(e => e.socium_tracking_number == path.id);
if(index === -1)
return { data };
_.set(data, `activities[${index}].${path.field}`, payload.data);
return {
data,
};
...
DetailsState.js -- dispatch functions to fetch details
const DetailsState = props => {
const initialState = {
details: null,
};
const [state, dispatch] = useReducer(DetailsReducer, initialState);
const getDetails = async () => {
try {
const res = await axios.get(url);
dispatch({ type: GET_DETAILS, payload: res.data.data[0].details});
}catch(err) {
console.log(err)
}
};
return (
<DetailsContext.Provider
value={{ details: state.details, getDetails }}
>
{ props.children }
</DetailsContext.Provider>
);
}
export default SchemaState;
DetailsReducer.js -- switch statement
export default (state, action) => {
switch (action.type) {
case GET_DETAILS:
return {
...state,
details: action.payload,
};
default:
return state;
}
};
ActivityTable.js -- component that consumes Activity Info
...
const ActivityTable = ({ activity }) => {
const activityContext = useContext(ActivityContext);
const { activities, filtered, getActivities } = activityContext;
const [order, setOrder] = React.useState('asc');
const [orderBy, setOrderBy] = React.useState(activities.wait_time);
// Get activity data on mount
useEffect(() => {
async function fetchData() {
await getActivities()
}
fetchData();
}, []);
...
CreateActivity.js -- component that consumes Activity and Details data
...
const CreateActivity = props => {
const activityContext = useContext(ActivityContext);
const { activities, filtered, getActivities, addActivity } = activityContext;
const detailsContext = useContext(DetailsContext);
const { details, getDetails } = detailsContext;
// Get activity and details data on mount
useEffect(() => {
async function fetchData() {
await getActivities();
await getSchema();
}
fetchData();
}, []);
...
I really tried to get smarter on these issues before approaching the SO community, so that my question(s) was more defined. But this is what I have. Happy to provide any info that I missed or clarify confusion. Thank you for your time