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...