How to write mapDispatchToProps when passing data? - redux

I'm struggling with Redux a little. I'm trying to dispatch an action to redux that will contain data - I can send the dispatch and get a successful response without it, so how do I rewrite the code so I can send data across?
I'm using RN image picker to choose an image. Once the user has chosen an image (in the getPhotoFromGallery function), it will get written to the local state where that local state will then be passed into a function dispatch in redux. I'm getting the error this.props.addImageToPost(imageData) is not a function
class MyForm extends React.Component {
state = {
imageData: null,
caption: null,
base64URI: null
}
//choose the photo.
getPhotoFromGallery = () => {
const { imageData } = this.state
ImagePicker.launchImageLibrary({}, (response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
}
else if (response.error) {
console.log('ImagePicker Error: ', response.error);
}
else {
//send image to redux
this.setState({ imageData: response });
this.setState({ base64URI: response.uri });
this.props.addImageToPost(imageData) // ????
}
});
};
//show image in component
showPickedImage() {
const { imageData } = this.state;
if (imageData !== null) {
return (
<Image
source={{ uri: imageData.uri }}
style={{ alignSelf: 'center', width: 90, height: 90, borderRadius: 20, marginLeft: 15 }}
/>
);
} else {
return (
<View>
<TouchableOpacity
style={{ alignSelf: 'center', width: 90, height: 90, borderRadius: 20, marginLeft: 15, alignItems: 'center', justifyContent: 'center', backgroundColor: 'white', shadowColor: "#000", shadowOffset: { width: 0, height: 5, }, shadowOpacity: 0.2, shadowRadius: 15, }}
onPress={this.getPhotoFromGallery}
>
<Icon name="camera" size={32} color="black" />
</TouchableOpacity>
</View>
);
}
}
render() {
const { image } = this.props;
return (
<View style={styles.myFormContainer}>
{this.showPickedImage()}
</View>
);
}
function mapStateToProps(state) {
return { imageData: state.post.imageData }
}
const mapDispatchToProps = {
addImageToPost, // ????
};
export default connect(mapStateToProps, mapDispatchToProps)(MyForm)

See Connect: Dispatching Actions with mapDispatchToProps.
It should be something like this
const mapDispatchToProps = dispatch => ({
addImageToPost: (imageData) => dispatch({ type: 'ActionType', payload: imageData })
});
or if you have an action creator
const mapDispatchToProps = dispatch => ({
addImageToPost: (imageData) => dispatch(myActionCreator(imageData))
});
and use it in your component like so
else {
//send image to redux
this.setState({ imageData: response });
this.setState({ base64URI: response.uri });
this.props.addImageToPost(imageData); // ???? correct
}

Related

NextJS shallow routing breaks anchor tags

In a next.js app, I have a card detail page that takes [id] as a parameter. By design, if an invalid id is passed (e.g. /card/pick-a-new-card), then getServerSideProps picks a random card instead. As suggested in the docs, I'm using shallow routing to then update the URL:
// /card/[id].tsx
useEffect(() => {
router.push(`/card/${card?.id}`, undefined, { shallow: true })
});
This works just fine. Except that it breaks my home button, which is rendered very plainly by:
<Button color="inherit" href="/">Home</Button>
Now this home button no longer works -- nothing appears to happen after one clicks it.
For now, I've worked around the issue with the old school solution of
window.history.pushState(null, '', `/card/${card?.id}`);
But I have no idea what about the shallow route is killing the home button -- that behavior seems very concerning to me.
So far, I have tried these things with no change in behavior:
using <Link> instead of a button.
using a navigation script in onClick instead of a simple href.
Here's the complete id.tsx page:
import { Card, Deck } from '#prisma/client';
import type { GetServerSideProps, NextPage } from 'next'
import { useRouter } from 'next/router';
import { MyAppBar } from '../../components/MyAppBar';
import { prisma } from '../../lib/prisma';
import { Button, Card as MuiCard, CardActions, CardContent, Container, Typography } from '#mui/material';
import dayjs from 'dayjs';
import { useEffect, useState } from 'react';
import useAlert from '../../components/useAlert';
import { formatLastUsedDate } from '../../lib/utils';
const CardPage: NextPage<{ card: Card | null, deck: Deck }> = ({ card, deck }) => {
const router = useRouter();
const { setAlert } = useAlert();
// update the URL
useEffect(() => {
// TODO: shallow routing sometimes kills all link navigation
// router.push(`/card/${card?.id}`, undefined, { shallow: true });
window.history.pushState(null, '', `/card/${card?.id}`);
});
// disable the button if it's just been clicked
const [justClicked, setJustClicked] = useState(false);
const refreshData = () => {
router.replace(router.asPath)
}
async function markUsed(cardId: number) {
const used = dayjs();
const data = { id: cardId, dateUsed: used.toISOString() }
try {
fetch(`/api/card/${cardId}`, {
body: JSON.stringify(data),
headers: { 'Content-Type': 'application/json' },
method: 'POST'
}).then(() => {
setAlert("Complete.", "success");
// TODO: why is this necessary to refresh the ui?
if (card !== null) { card.dateUsed = used.toDate() }
});
} catch (error) {
setAlert("An error occurred while updating the record.", "error");
}
}
return (
<Container maxWidth='md' sx={{ paddingLeft: { xs: 0, sm: 0 }, paddingRight: { xs: 0, sm: 0 } }}>
<MyAppBar title={deck.deckName}>
</MyAppBar>
<MuiCard key={card?.id || 0} sx={{
paddingLeft: { xs: 2, sm: 5 }, paddingRight: { xs: 2, sm: 5 },
minWidth: 275, minHeight: "40vh",
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
}}>
<CardContent sx={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
flexFlow: 'column',
flexGrow: 1,
justifyContent: 'space-between',
}}>
<Typography variant="h4" component="div" sx={{ flex: '0 1 auto' }}>
{card?.name}
</Typography>
<Typography sx={{ mt: 10, px: { sm: 4, md: 10 }, flex: '1 1 auto' }} variant="h5" component="div">
{card ? card.description : 'There are no cards in this deck.'}
</Typography>
<Typography sx={{ marginTop: "auto", pt: 8, flex: '0 1 40px' }} color="text.secondary" >
{formatLastUsedDate(card?.dateUsed ?? '')}
</Typography>
</CardContent>
<CardActions sx={{ marginTop: 'auto' }}>
<Button disabled={card === null}
onClick={e => {
setJustClicked(false);
router.push(`/card/pick?deck=${deck.id}`);
}}>
pick a random card from this deck
</Button>
<Button disabled={justClicked || card === null} onClick={e => {
e.preventDefault();
setJustClicked(true);
markUsed(card?.id ?? 0);
}} >mark as used</Button>
</CardActions>
</MuiCard>
</Container>
)
}
export default CardPage
export const getServerSideProps: GetServerSideProps = async (context) => {
// two options: either a specific card id passed, or else a deck id,
// from which we should randomly pick
const dateBefore = dayjs().subtract(3, 'day').toDate(); // don't re-pick any items for three days
// TODO: add a property for "don't pick again" to avoid the last ID picked
let deckId = context.query.deck;
let cardId = context.query.id;
let deck: Deck | null = null;
let card: Card | null = null;
if (deckId !== undefined) {
const filter = {
where: {
idDeck: Number(deckId),
OR: [
{ dateUsed: null },
{ dateUsed: { lte: dateBefore } }
]
}
};
// pick a random card
const cardCount = await prisma.card.count({
...filter
});
// are there any cards within the date range?
if (cardCount === 0) {
// no: just pick *any* card from the deck
card = await prisma.card.findFirst({
where: {
idDeck: Number(deckId)
}
});
} else {
const skip = Math.floor(Math.random() * cardCount);
card = await prisma.card.findFirst({
skip: skip,
...filter
});
}
}
if (card === null && cardId !== '' && !Number.isNaN(Number(cardId))) {
card = await prisma.card.findFirst({
where: {
id: Number(cardId)
}
});
}
if (card !== null) { deckId = card?.idDeck.toString() ?? '0'; }
deck = await prisma.deck.findFirst({
where: {
id: Number(deckId)
}
}) || { id: 0, deckName: "None" } as Deck;
return {
props: {
card: JSON.parse(JSON.stringify(card)), // TODO: research this prisma Date hack; see https://stackoverflow.com/questions/72176573/object-object-object-cannot-be-serialized-as-json-please-only-return-js
deck
}
}
}
Your useEffect is missing a dependency array. Try this:
useEffect(() => {
router.push(`/card/${card?.id}`, undefined, { shallow: true })
}, []);

How to Use Multiple Array to store state values With Redux in React Native

Here I have use Redux to manage state value but is not working..
And i have two arrays to hold the state values but it is not showing any record i don't know why it is not working..
notesReducer.js
import remove from 'lodash.remove'
// Action Types
export const ADD_NOTE = 'ADD_NOTE'
export const DELETE_NOTE = 'DELETE_NOTE'
export const ADD_NUMBER = 'ADD_NUMBER'
export const DELETE_NUMBER = 'DELETE_NUMBER'
// Action Creators
let noteID = 0
let numberID = 0
export function addnote(note) {
return {
type: ADD_NOTE,
id: noteID++,
note
}
}
export function deletenote(id) {
return {
type: DELETE_NOTE,
payload: id
}
}
export function addnumber(number) {
return {
type: ADD_NUMBER,
id: numberID++,
number
}
}
export function deletenumber(id) {
return {
type: DELETE_NUMBER,
payload: id
}
}
// reducer
const INITIAL_STATE = {
note: [], // for holds notes
number: [] // for holds numbers
};
function notesReducer(state = INITIAL_STATE, action) {
switch (action.type) {
case ADD_NOTE:
return {
...state,
note: [
...state.note,
{
id: action.id,
note: action.note
}
]
};
case DELETE_NOTE:
const note = remove(state.note, obj => obj.id != action.payload);
return {...state, note};
case ADD_NUMBER:
return {
...state,
number: [
...state.number,
{
id: action.id,
number: action.number
}
]
};
case DELETE_NUMBER:
const number = remove(state.number, obj => obj.id != action.payload);
return {...state, number}
default:
return state
}
}
export default notesReducer
And single Store
store.js
import { createStore } from 'redux'
import notesReducer from './notesApp'
const store = createStore(notesReducer)
export default store
ViewNotes.js
import React from 'react'
import { Button, StyleSheet, View, FlatList } from 'react-native'
import { Text, FAB, List } from 'react-native-paper'
import { useSelector, useDispatch } from 'react-redux'
import { addnote, deletenote } from '../redux/notesApp'
import { Ionicons } from "react-native-vector-icons";
import Header from '../components/Header'
function ViewNotes({ navigation }) {
const notes = useSelector(state => state)
const dispatch = useDispatch()
const addNote = note => dispatch(addnote(note))
const deleteNote = id => dispatch(deletenote(id))
return (
<>
<Header titleText='White List' />
<View style={styles.container}>
<Button title="Go back" onPress={() => navigation.goBack()} />
{notes.length === 0 ? (
<View style={styles.titleContainer}>
<Text style={styles.title}>You do not have any notes</Text>
</View>
) : (
<FlatList
data={notes}
renderItem={({ item }) => (
<List.Item
title={item.note.noteTitle}
description={item.note.noteValue}
right={props => <List.Icon {...props} icon="close" />}
descriptionNumberOfLines={1}
titleStyle={styles.listTitle}
onPress={() => deleteNote(item.id)}
/>
)}
keyExtractor={item => item.id.toString()}
/>
)}
<FAB
style={styles.fab}
small
icon='plus'
label='Add new number'
onPress={() =>
navigation.navigate('AddNotes', {
addNote
})
}
/>
</View>
</>
)
}
ViewNotes.navigationOptions = {
title : 'Always Allows Calls'
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
paddingHorizontal: 10,
paddingVertical: 20
},
titleContainer: {
alignItems: 'center',
justifyContent: 'center',
flex: 1
},
title: {
fontSize: 20
},
fab: {
position: 'absolute',
margin: 20,
right: 0,
bottom: 10
},
listTitle: {
fontSize: 20
}
})
export default ViewNotes
AddNote.js
import React, { useState } from 'react'
import { View, StyleSheet } from 'react-native'
import { IconButton, TextInput, FAB } from 'react-native-paper'
import Header from '../components/Header'
function AddNote({ navigation }) {
const [noteTitle, setNoteTitle] = useState('')
const [noteValue, setNoteValue] = useState('')
function onSaveNote() {
navigation.state.params.addNote({ noteTitle, noteValue })
navigation.goBack()
}
return (
<>
<Header titleText='Add a new number' />
<IconButton
icon='close'
size={25}
color='white'
onPress={() => navigation.goBack()}
style={styles.iconButton}
/>
<View style={styles.container}>
<TextInput
label='Add Title Here'
value={noteTitle}
mode='outlined'
onChangeText={setNoteTitle}
style={styles.title}
/>
<TextInput
label='Add Note Here'
value={noteValue}
onChangeText={setNoteValue}
mode='flat'
multiline={true}
style={styles.text}
scrollEnabled={true}
returnKeyType='done'
blurOnSubmit={true}
/>
<FAB
style={styles.fab}
small
icon='check'
disabled={noteTitle == '' ? true : false}
onPress={() => onSaveNote()}
/>
</View>
</>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
paddingHorizontal: 20,
paddingVertical: 20
},
iconButton: {
backgroundColor: 'rgba(46, 113, 102, 0.8)',
position: 'absolute',
right: 0,
top: 40,
margin: 10
},
title: {
fontSize: 24,
marginBottom: 20
},
text: {
height: 300,
fontSize: 16
},
fab: {
position: 'absolute',
margin: 20,
right: 0,
bottom: 0
}
})
export default AddNote
It is not Showing any record So How i fixed it..
Please Help me..
Change useSelector(state => state) to :
useSelector(state => state.note)
Because your store is like {note: [], number: []}

getting lat/long coordinates from firebase/firestore collection

im relative new to react native and firebase and it would be awesome if anyone could help me with this problem. currently when im adding new posts to my firebase collection i display all post with a flatlist and it works fine. but is it possible to get only the currentLatitude and currentLongitude for my markers? my target is to generate a new marker for each post.
Events = []
this.firestore.collection("Events").get().then(snapshot => {
snapshot.forEach(doc => {
Events.push(doc.data())
})
})
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<MapView
provider={PROVIDER_GOOGLE}
mapType='hybrid'
showsUserLocation style={{flex: 1}}>
<MapView.Marker
coordinate={{latitude: //currentLatitude,
longitude: //currntLongitude}}
title={("Test")}
description={("Test")}
/>
</MapView>
</View>
</SafeAreaView>
);
}
}
#DevAS thanks for your patience.. this was made from 3 different .js files.. but I don't now how to get it just into the map.js.
The final result should look something like this:
enter image description here
Everything except for the lat/lng cords are supposed to be in the callout-window.
Item.js:
import { Ionicons } from '#expo/vector-icons';
import React from 'react';
import { Image, StyleSheet, Text, View } from 'react-native';
import Fire from '../screens/Fire'
const profileImageSize = 36;
const padding = 12;
export default class Item extends React.Component {
state = {
user: {}
};
componentDidMount() {
const user = this.props.uid || Fire.shared.uid;
this.unsubscribe = Fire.shared.firestore
.collection("users")
.doc(user)
.onSnapshot(doc => {
this.setState({ user: doc.data() });
});
if (!this.props.imageWidth) {
// Get the size of the web image
Image.getSize(this.props.image, (width, height) => {
this.setState({ width, height });
});
}
}
componentWillUnmount() {
this.unsubscribe();
}
render() {
const { title, address, name, imageWidth, imageHeight, image, currentLatitude, currentLongitude } = this.props;
// Reduce the name to something
const imgW = imageWidth || this.state.width;
const imgH = imageHeight || this.state.height;
const aspect = imgW / imgH || 1;
return (
<View>
<Header image={{ uri: this.state.user.avatar }} name={this.state.user.name} />
<Image
resizeMode="contain"
style={{
backgroundColor: "#D8D8D8",
width: "100%",
aspectRatio: aspect
}}
source={{ uri: image }}
/>
<Metadata
name={this.state.user.name}
address={address}
title={title}
currentLongitude={currentLongitude}
currentLatitude={currentLatitude}
/>
</View>
);
}
}
const Metadata = ({ name, address, title, currentLongitude, currentLatitude}) => (
<View style={styles.padding}>
<IconBar />
<Text style={styles.text}>{name}</Text>
<Text style={styles.subtitle}>{address}</Text>
<Text style={styles.subtitle}>{title}</Text>
<Text style={styles.subtitle}>Lat: {currentLatitude}</Text>
<Text style={styles.subtitle}>Lng: {currentLongitude}</Text>
</View>
);
const Header = ({ name, image }) => (
<View style={[styles.row, styles.padding]}>
<View style={styles.row}>
<Image style={styles.avatar} source={image} />
<Text style={styles.text}>{name}</Text>
</View>
<Icon name="ios-more" />
</View>
);
const Icon = ({ name }) => (
<Ionicons style={{ marginRight: 8 }} name={name} size={26} color="black" />
);
const IconBar = () => (
<View style={styles.row}>
<View style={styles.row}>
<Icon name="ios-heart-empty" />
<Icon name="ios-chatbubbles" />
<Icon name="ios-send"/>
</View>
<Icon name="ios-bookmark" />
</View>
);
const styles = StyleSheet.create({
text: { fontWeight: "600" },
subtitle: {
opacity: 0.8
},
row: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center"
},
padding: {
padding
},
avatar: {
aspectRatio: 1,
backgroundColor: "#D8D8D8",
borderWidth: StyleSheet.hairlineWidth,
borderColor: "#979797",
borderRadius: profileImageSize / 2,
width: profileImageSize,
height: profileImageSize,
resizeMode: "cover",
marginRight: padding
}
});
List.js
import React from 'react';
import { FlatList } from 'react-native';
import Footer from './Footer';
import Item from './Item';
class List extends React.Component {
renderItem = ({ item }) => <Item {...item} />;
keyExtractor = item => item.key;
render() {
const { onPressFooter, ...props } = this.props;
return (
<FlatList
keyExtractor={this.keyExtractor}
ListFooterComponent={footerProps => (
<Footer {...footerProps} onPress={onPressFooter} />
)}
renderItem={this.renderItem}
{...props}
/>
);
}
}
export default List;
FeedScreen.js
import firebase from "firebase";
import React, { Component } from "react";
import { LayoutAnimation, RefreshControl } from "react-native";
import List from "../components/List";
import Fire from "./Fire";
// Set the default number of images to load for each pagination.
const PAGE_SIZE = 5;
console.disableYellowBox = true;
export default class FeedScreen extends Component {
state = {
loading: false,
data: {}
};
componentDidMount() {
// Check if we are signed in...
if (Fire.shared.uid) {
// If we are, then we can get the first 5 posts
this.makeRemoteRequest();
} else {
// If we aren't then we should just start observing changes. This will be called when the user signs in
firebase.auth().onAuthStateChanged(user => {
if (user) {
this.makeRemoteRequest();
}
});
}
}
// Append the item to our states `data` prop
addPosts = posts => {
this.setState(previousState => {
let data = {
...previousState.data,
...posts
};
return {
data,
// Sort the data by timestamp
posts: Object.values(data).sort((a, b) => a.timestamp < b.timestamp)
};
});
};
// Call our database and ask for a subset of the user posts
makeRemoteRequest = async lastKey => {
// If we are currently getting posts, then bail out..
if (this.state.loading) {
return;
}
this.setState({ loading: true });
// The data prop will be an array of posts, the cursor will be used for pagination.
const { data, cursor } = await Fire.shared.getPaged({
size: PAGE_SIZE,
start: lastKey
});
this.lastKnownKey = cursor;
// Iteratively add posts
let posts = {};
for (let child of data) {
posts[child.key] = child;
}
this.addPosts(posts);
// Finish loading, this will stop the refreshing animation.
this.setState({ loading: false });
};
// Because we want to get the most recent items, don't pass the cursor back.
// This will make the data base pull the most recent items.
_onRefresh = () => this.makeRemoteRequest();
// If we press the "Load More..." footer then get the next page of posts
onPressFooter = () => this.makeRemoteRequest(this.lastKnownKey);
render() {
// Let's make everything purrty by calling this method which animates layout changes.
LayoutAnimation.easeInEaseOut();
return (
<List
refreshControl={
<RefreshControl
refreshing={this.state.loading}
onRefresh={this._onRefresh}
/>
}
onPressFooter={this.onPressFooter}
data={this.state.posts}
/>
);
}
}

How do I display list of objects from Firebase in React Native?

I have retrieved data from my Firebase-database, and displayed it correctly earlier using a map function. This is the list of objects retrieved correctly
This time I tried to retrieve the sorted list using orderbychild, and I tried to map over the list, but it wont enter the map function. I have console logged the state which says what shows this in the picture. It seems to be and empty list, but it still has objects inside
Here is the file: https://pastebin.com/RLJMpzWN
Here is the Firebase setup
My question is, how do I display my list of objects?
import React from "react";
import { StyleSheet, View, Text, FlatList } from "react-native";
import firebase from 'firebase/app';
export default class Card extends React.Component {
constructor(props) {
super(props);
this.state = {
highScoreList: null,
isDataLoaded: false
}
}
componentDidMount() {
const hList = [];
const ref = firebase.database().ref('users')
ref.orderByChild('hours').on('child_added', function(snapshot) {
hList.push({
id: snapshot.key,
hours: snapshot.val().hours,
name: snapshot.val().name
});
});
this.setState({
highScoreList: hList,
isDataLoaded: true
})
}
render(){
if(this.state.isDataLoaded && this.state.highScoreList){
return (
<View style={styles.card}>
{this.state.highScoreList.map( user => <Text key = {user.key} style = {{textAlign: 'center', marginBottom: 10}}>{user.name} {user.hours}</Text>)}
</View>
)
}else{
console.log("State var tom")
return (<Text> Waiting for data</Text>)
}
}
}
const styles = StyleSheet.create({
card: {
flex: 1, flexDirection: 'row',
backgroundColor: "#fff",
paddingVertical: 20,
paddingHorizontal: 10,
borderRadius: 20,
minHeight: 333
},
text: {
fontSize: 30,
marginBottom: 20,
color: "black",
},
});
#Simen96 I would recommend you to refactor your component to something like this:
constructor(props) {
super(props);
this.state = {
highScoreList: [],
isDataLoaded: false
}
}
componentDidMount() {
const ref = firebase.database().ref('users')
ref.orderByChild('hours').on('child_added', snapshot => {
this.state.highScoreList.push({
id: snapshot.key,
hours: snapshot.val().hours,
name: snapshot.val().name
});
});
}
render(){
if(this.state.highScoreList.length){
return (
<View style={styles.card}>
{this.state.highScoreList.map( user => <Text key = {user.key} style = {{textAlign: 'center', marginBottom: 10}}>{user.name} {user.hours}</Text>)}
</View>
)
}else{
console.log("State var tom")
return (<Text> Waiting for data</Text>)
}
}
The function componentDidMount and the 'child_added' callback will not execute sequentially because 'child_added' callback is asynchronous and setState will not wait for this callback to be triggered.

View not updating state Redux, React, Firebase

I am using redux to store and fetch my data from Firebase. The data is stored successfully, however, the view MyActivities is not updated with the new data. Am I doing something wrong here ?
I need to rerender the whole application for the views to be updated with the new data stored in Firebase.
I didn't add all the code used in this example.
ActivitiesAction.js
import firebase from 'firebase';
import { Navigation } from 'react-native-navigation';
import {
ACTIVITIES_FETCH_SUCCESS,
ACTIVITIES_SEND_SUCCESS,
SUBACTIVITY_SEND_SUCCESS
} from './types';
export const activitiesFetch = () => {
return (dispatch) => {
firebase.database().ref('users_data/s80GnOQu22W4XLLYbuKUBC2BzkY2/').once('value')
.then((snapshot) => {
dispatch({
type: ACTIVITIES_FETCH_SUCCESS,
payload: snapshot.val()
});
});
};
};
export const activitiesSend = (activityDescription,
activityDate, category, notification, alarm) => {
const ref = firebase.database()
.ref('users_data/s80GnOQu22W4XLLYbuKUBC2BzkY2/activities/cheduled_activities');
const activity = ref.push();
const ref2 = firebase.database()
.ref('users_data/s80GnOQu22W4XLLYbuKUBC2BzkY2/activities/all_activities');
const activityList = ref2.push();
return (dispatch) => {
activity.set({
activityDescription,
activityDate,
category,
// time: this.state.time,
notification,
alarm
}).then(activityCreated => {
dispatch({ type: ACTIVITIES_SEND_SUCCESS, payload: activityCreated });
activityList.set({
activityDescription,
category
}).then(listActivity => {
dispatch({ type: SUBACTIVITY_SEND_SUCCESS, payload: listActivity });
});
});
};
};
ActivitiesReducer.js
import {
ACTIVITIES_FETCH_SUCCESS,
ACTIVITIES_SEND_SUCCESS,
SUBACTIVITY_SEND_SUCCESS
} from '../actions/types';
const INITIAL_STATE = { activitiesData: '', activityCreated: null, listActivity: null };
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case ACTIVITIES_FETCH_SUCCESS:
return { ...state, activitiesData: action.payload };
case ACTIVITIES_SEND_SUCCESS:
return { ...state, activityCreated: action.payload };
case SUBACTIVITY_SEND_SUCCESS:
return { ...state, listActivity: action.payload };
default:
return state;
}
};
MyActivities.js
import React, { Component } from 'react';
import { Container, Content, View } from 'native-base';
import { connect } from 'react-redux';
import _ from 'lodash';
import { activitiesFetch } from '../actions/ActivitiesAction';
import Activity from './Activity';
class MyActivities extends Component {
constructor(props) {
super(props);
}
componentWillMount() {
this.props.activitiesFetch();
}
componentWillReceiveProps(nextProps) {
this.setState({ activitiesData: nextProps });
console.log('next props:', nextProps);
}
componentWillUpdate(nextProps, nextState) {
console.log('next props:', nextProps);
}
renderActivities() {
// this.setState({ data: this.props.activitiesArray });
console.log('acti():', this.props.activitiesData);
const activitiesArray = _.values(this.props.activitiesData);
console.log('acti[]:', activitiesArray);
const list = _.values(activitiesArray[0]) || [];
const act = list.map((activities) => (activities));
console.log('acti[]:', act);
const activities = _.values(act[1]);
return (
activities.map((singleActivity, i) => (
<Activity
key={i}
Title={singleActivity.activityDescription}
Author={activitiesArray[1].full_name}
Time={singleActivity.time}
PeopleStats={'0'}
/>
))
);
}
render() {
return (
<Container>
{/* <HeaderActivities /> */}
<Content style={styles.Content}>
{/* <ScrollView style={{ flex: 1 }}> */}
<View style={styles.styleView}>
{this.renderActivities()}
</View>
{/* </ScrollView> */}
</Content>
</Container>
);
}
}
const mapStateToProps = state => {
return {
// activitiesArray: _.values(state.activitiesData)
activitiesData: state.activitiesData
};
};
const styles = {
Content: {
backgroundColor: '#F0F5F7',
},
styleView: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'center',
alignItems: 'center',
// alignItems: 'flex-start',
// alignContent: 'flex-start'
},
ButtonActive: {
borderBottomColor: '#FF8600',
borderBottomWidth: 3,
paddingBottom: 3,
borderRadius: 0
}
};
export default connect(mapStateToProps, { activitiesFetch })(MyActivities);
Use the redux and react dev tools to check
did the expected action dispatch?
does the state change match your expectations?
do components have the props you expect them to have?

Resources