Rendering Firebase data into FlatList - firebase

I am using React Native, Rematch for Redux and Firebase Firestore. I am attempting to pull data from my Firebase database and populate it inside my FlatList. The problem is, it is not giving me any error and it giving me a blank white screen. I do not know where I am going wrong.
This is what my database looks like - list of activities
This is what my Rematch for Redux store looks like:
import firebase from 'firebase';
import db from '../config/firebase'
const activity = {
state: {},
reducers: {
activities(state, payload) {
return {
...state,
...payload
}
},
},
effects: {
async getActivities() {
try {
const response = await db.collection('activities').get()
//console.log(response.docs.map(doc => doc.data()))
return dispatch({ type: 'activity/activities', payload: response.docs.map(doc => doc.data()) })
} catch (err) {
alert(err)
}
},
}
}
export default activity
Here is the component where I am using the FlatList:
import * as React from 'react';
import {
Text,
TouchableOpacity,
View,
FlatList,
ImageBackground
}
from 'react-native';
import styles from '../styles'
import { connect } from 'react-redux';
import '#expo/vector-icons';
import 'redux';
class Activities extends React.Component {
state = {
movetoArray: [],
outputActivity: [],
};
async componentDidMount() {
const activities = await this.props.getActivities()
this.state.movetoArray = Object.values(activities)
this.state.outputActivity = Object.entries(this.state.movetoArray[1]).map(item => ({ ...item[1], key: item[0] }));
//this.state.arrayActivity = Object.entries(activities).map(item => ({...item[1], key: item[0]}));
console.log(this.state.outputActivity)
}
_renderItem = ({ item }) => (
<TouchableOpacity
onPress={() => this.props.navigation.navigate('activitiesMD',
{
title: item.name,
objectData: item.data
})}>
<ImageBackground source={item.image} style={styles.inputTiles} imageStyle={{ borderRadius: 10 }}>
<View style={styles.inputTileTextView}>
<Text style={[styles.inputTileText, { color: item.colour }]}>{item.name}</Text>
</View>
</ImageBackground>
</TouchableOpacity>
);
render() {
const { routeName } = this.props.navigation.state
return (
<View style={styles.container}>
<FlatList
data={this.state.outputActivity}
keyExtractor={item => item.id}
renderItem={this._renderItem}
/>
</View>
);
}
}
const mapState = (state) => ({
activity: state.activity,
})
const mapDispatch = (dispatch) => ({
getActivities: () => dispatch.activity.getActivities(),
})
export default connect(mapState, mapDispatch)(Activities)
I do not know why I am getting this outcome. Please help me :)

If you directly mutate state in React then the component won't re-render. Please use this.setState({ ... }) like so:
- this.state.movetoArray = Object.values(activities)
- this.state.outputActivity = Object.entries(this.state.movetoArray[1]).map(item => ({ ...item[1], key: item[0] }));
+ this.setState({ movetoArray: Object.values(activities), outputActivity: Object.entries(this.state.movetoArray[1]).map(item => ({ ...item[1], key: item[0] })) })

Related

React Native. How to show screens according to the User Authentication status

I'm developing my first ever React Native App. I have created Login/SignUp screen and connect these with Firebase for Authentication. As well as i have some screen containing Drawers. I want that if the user is Not Authenticated. Login/Signup screen should show otherwise HomeScreen(having many drawers) will show. For this i did some checks in MainRouteComponent but its not working
I am uploading my Code of all the related Components as well as some redux code i have used here. I know it will take time to go through that much code but i tried a lot and i am struggling now. Hope many of you will help. :)
Here is my code:-
App.js
import React from 'react';
import Main from './components/MainComponent';
import MainRoute from './components/MainRouteComponent'
import { Provider } from 'react-redux';
import { ConfigureStore } from './redux/configureStore';
import { PersistGate } from 'redux-persist/es/integration/react'
import { Loading } from './components/LoadingComponent';
const { persistor, store } = ConfigureStore();
export default App = () =>{
return (
<Provider store={store}>
<PersistGate
loading={<Loading />}
persistor={persistor}>
<MainRoute/>
</PersistGate>
</Provider>
);
}
MainRouteComponent.js
import React, { useState } from 'react';
import Main from './MainComponent';
import Root from './RootComponent';
import { auth } from '../firebase/firebase';
const AuthContext = React.createContext();
const MainRoute = () => {
const user = auth.currentUser
console.log("User", user)
console.log("Auth", isAuth)
return(
{(user == null) ?
<Root />
:
<Main />
}
)
}
export default MainRoute;
RootComponent.js
import React, {Component} from 'react';
import { createStackNavigator } from 'react-navigation';
import * as Animatable from 'react-native-animatable';
import SplashScreen from './SplashScreen';
import Login from './LoginComponent';
import Register from './RegistrationComponent';
const RootStack = createStackNavigator({
SplashScreen: { screen: SplashScreen,
navigationOptions: ({ navigation }) => ({
headerStyle: {
backgroundColor: "#512DA8"
},
headerTitle: "Welcome Foodies",
headerTintColor: '#fff',
headerTitleStyle: {
color: "#fff",
alignItems: 'center'
}
})
},
LoginComponent: {
screen: Login,
navigationOptions: ({ navigation }) => ({
headerStyle: {
backgroundColor: "#512DA8"
},
headerTitle: "Login",
headerTintColor: '#fff',
headerTitleStyle: {
color: "#fff",
alignItems: 'center'
}
})
},
Register: {
screen: Register,
navigationOptions: ({ navigation }) => ({
headerStyle: {
backgroundColor: "#512DA8"
},
headerTitle: "Sign Up",
headerTintColor: '#fff',
headerTitleStyle: {
color: "#fff",
alignItems: 'center'
}
})
},
},
{
initialRouteName: 'SplashScreen',
navigationOptions: ({ navigation }) => ({
headerStyle: {
backgroundColor: "#512DA8"
},
headerTintColor: '#fff',
headerTitleStyle: {
color: "#fff"
}
})
}
);
class Root extends Component {
render() {
return (
<RootStack />
)
}
}
export default Root;
LoginComponent.js
import React, { Component } from 'react';
import { View, StyleSheet, Text, ScrollView, Image } from 'react-native';
import { Input, CheckBox, Button, Icon } from 'react-native-elements';
import * as SecureStore from 'expo-secure-store';
import { loginUser} from '../redux/ActionCreators';
import { connect } from 'react-redux';
const mapStateToProps = state => {
return {
auth: state.AUTH
}
}
const mapDispatchToProps = dispatch => {
return {
loginUser: (creds) => dispatch(loginUser(creds))
}
}
class Login extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
password: '',
remember: false
}
}
componentDidMount() {
SecureStore.getItemAsync('userinfo')
.then((userdata) => {
let userinfo = JSON.parse(userdata);
if (userinfo) {
this.setState({email: userinfo.email});
this.setState({password: userinfo.password});
this.setState({remember: true})
}
})
}
static navigationOptions = {
title: 'Login',
tabBarIcon: ({ tintColor }) => (
<Icon
name='sign-in'
type='font-awesome'
size={24}
iconStyle={{ color: tintColor }}
/>
)
};
handleLogin() {
this.props.loginUser({email: this.state.email, password: this.state.password});
//event.preventDefault();
if (this.state.remember)
SecureStore.setItemAsync('userinfo', JSON.stringify({email: this.state.email, password: this.state.password}))
.catch((error) => console.log('Could not save user info', error));
else
SecureStore.deleteItemAsync('userinfo')
.catch((error) => console.log('Could not delete user info', error));
this.setState({
email: '',
password: '',
remember: false
})
this.props.navigation.navigate('Home')
}
render() {
const { navigate } = this.props.navigation;
return (
<View style={styles.container}>
<Input
placeholder="Email"
leftIcon={{ type: 'font-awesome', name: 'envelope-o' }}
onChangeText={(email) => this.setState({email})}
value={this.state.email}
containerStyle={styles.formInput}
/>
<Input
placeholder="Password"
leftIcon={{ type: 'font-awesome', name: 'key' }}
onChangeText={(password) => this.setState({password})}
value={this.state.password}
containerStyle={styles.formInput}
/>
<CheckBox title="Remember Me"
center
checked={this.state.remember}
onPress={() => this.setState({remember: !this.state.remember})}
containerStyle={styles.formCheckbox}
/>
<View style={styles.formButton}>
<Button
onPress={() => this.handleLogin()}
title="Login"
icon={
<Icon
name='sign-in'
type='font-awesome'
size={24}
color= 'white'
/>
}
buttonStyle={{
backgroundColor: "#512DA8"
}}
/>
</View>
<View style={styles.formButton}>
<Button
onPress={() => navigate('Register')}
title="Register"
clear
icon={
<Icon
name='user-plus'
type='font-awesome'
size={24}
color= 'blue'
/>
}
titleStyle={{
color: "blue"
}}
buttonStyle={{
backgroundColor: "transparent"
}}
/>
</View>
</View>
);
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Login);
ActionCreator.js
import * as ActionTypes from './ActionTypes';
import { auth, firestore, fireauth, firebasestore } from '../firebase/firebase';
export const requestLogin = () => {
return {
type: ActionTypes.LOGIN_REQUEST
}
}
export const receiveLogin = (user) => {
return {
type: ActionTypes.LOGIN_SUCCESS,
user
}
}
export const loginError = (message) => {
return {
type: ActionTypes.LOGIN_FAILURE,
message
}
}
export const loginUser = (creds) => (dispatch) => {
// We dispatch requestLogin to kickoff the call to the API
dispatch(requestLogin(creds))
return auth.signInWithEmailAndPassword(creds.email, creds.password)
.then(() => {
var user = auth.currentUser;
dispatch(fetchFavorites());
dispatch(receiveLogin(user));
})
.then(response => { console.log('Login Successful', response); alert('Thank you for login!'); })
.catch(error => {console.log('Error', error); alert(error)})
.catch(error => dispatch(loginError(error.message)))
};
I also have Login Reducer as auth.js as i thought this can help in checking authentication to show screen accordingly.
auth.js
import * as ActionTypes from './ActionTypes';
export const Auth = (state = {
isLoading: false,
isAuthenticated: false,
user: null,
errMess: null
}, action) => {
switch (action.type) {
case ActionTypes.LOGIN_REQUEST:
return {...state,
isLoading: true,
isAuthenticated: false,
};
case ActionTypes.LOGIN_SUCCESS:
return {...state,
isLoading: false,
isAuthenticated: true,
errMess: '',
user: action.user
};
case ActionTypes.LOGIN_FAILURE:
return {...state,
isLoading: false,
isAuthenticated: false,
errMess: action.message
};
case ActionTypes.LOGOUT_REQUEST:
return {...state,
isLoading: true,
isAuthenticated: true
};
case ActionTypes.LOGOUT_SUCCESS:
return {...state,
isLoading: false,
isAuthenticated: false,
token: '',
user: null
};
default:
return state
}
}
Make separate routing for the stack screens which you don't want to be shown ! Try to make 2 stacks!

Why are my props `undefined` when using redux and react Native?

I followed all the steps to create a store, but I when I try to access my props, they are undefined. I am using react Native , redux, and the connect component from 'react-redux'. Please help . I cant move forward.
this is where I connect props to state :
const mapStateToProps = (state) => ({
location : state.location
})
export default connect(mapStateToProps)(MapsScreen);
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent:'center',
alignContent:'center',
}
})
This is the component :
import LocationComp from './location'
import {connect} from 'react-redux';
import * as actions from '../../../redux/actions'
import MapView from 'react-native-maps';
export class MapsScreen extends React.Component {
state = {
isLoading : true
}
handleLanguage = (loco) => {
store.dispatch(actions.newLocation(loco))
this.setState({ isLoading: !this.state.isLoading })
console.log(store.getState())
}
render() {
return (
<View style = {{flex :1}}>
{this.state.isLoading === true ?
(
<LocationComp getLocation = {this.handleLanguage}/>
):(
<MapView
style={{flex:1}}
initialRegion={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}>
{console.log(this.props.location)}
</MapView>
)}
</View>
);
}
}
My store:
import {createStore, applyMiddleware} from 'redux'
import reducer from './reducer'
import {addTest} from './actions'
import thunk from 'redux-thunk'
export default store = createStore(reducer, applyMiddleware(thunk))
My reducer :
import {UPDATE_TEST, UPDATE_LOCATION,} from './actions'
import { combineReducers} from 'redux'
const merge = (prev, next ) => Object.assign({}, prev, next)
const hustleReducer = (state = [], action) => {
if(action.type === UPDATE_TEST) {
return [...state, action.payload]
}
return state
}
const locoReducer = (state = {}, action) => {
if(action.type === UPDATE_LOCATION){
return merge(state.location, action.payload)
}
return state
}
export default reducer = combineReducers({
hustleList : hustleReducer,
location : locoReducer,
})
my actions :
/// action creators
export const UPDATE_TEST= 'UPDATE_TEST'
export const UPDATE_LOCATION = 'UPDATE_LOCATION'
export const addTest = newContact => ({
type : UPDATE_TEST,
payload : newContact
})
export const newLocation = newLocation =>({
type : UPDATE_LOCATION,
payload : newLocation
})
You dont need merge, try return something like return {{...state.location}, {...action.payload}}

Rematch for Redux: Setting State to that of the Payload when Signing Up

How do I set state to that of my payload? I would like my global state to have the recent changes, not the payload. Please could someone explain why/how this is happening? Do I need to create another reducer/effect to set the state? I want to set this state as global within the app. I would greatly appreciate it.
I am using the following:
Firebase Firestore
Rematch for Redux
React Native
This is My debugger (image).
Result of the code below.
Here is my code:
Index.js
import { init } from '#rematch/core'
import user from './user'
const models = {
user,
}
const store = init({
models,
})
export default { getState, dispatch } = store
Model.js (User.js)
import firebase from 'firebase';
import db from '../config/firebase'
const user = {
state: {},
reducers: {
login(userData) {
return userData
},
email(state, email) {
return { ...state, email }
},
password(state, password) {
return { ...state, password }
},
username(state, username) {
return { ...state, username }
},
fullname(state, fullname) {
return { ...state, fullname }
},
},
effects: () => ({
async signup() {
const { email, password, username, fullname } = getState().user
const response = await firebase.auth().createUserWithEmailAndPassword(email, password)
if (response.user.uid) {
const userData = {
uid: response.user.uid,
email: email,
username: username,
fullname: fullname,
bio: 'test',
gender: 'teste',
phoneNum: 'teste',
profilePic: 'te',
status: 'teste',
}
db.collection('users').doc(response.user.uid).set(userData)
alert(userData.uid)
return dispatch.user.login(userData)
}
}
})
}
export default user
SignUp.js
import * as React from 'react';
import {
TextInput,
Text,
KeyboardAvoidingView,
SafeAreaView,
TouchableOpacity,
Alert,
}
from 'react-native';
import styles from '../styles'
import { connect } from 'react-redux';
import '#expo/vector-icons';
import 'redux';
class Signup extends React.Component {
onPress = () => {
this.props.SignUp()
this.props.navigation.navigate('Home')
}
render() {
const { routeName } = this.props.navigation.state
return (
<SafeAreaView style={styles.container}>
<KeyboardAvoidingView behavior='position'>
<Text style={styles.mainText}>
EMAIL
</Text>
<TextInput
style={styles.inputText}
editable={routeName === 'Signup' ? true : false}
value={this.props.user.email}
onChangeText={input => this.props.setEmail(input)}
/>
<Text style={styles.mainText}>
PASSWORD
</Text>
<TextInput
style={styles.inputText}
editable={routeName === 'Signup' ? true : false}
value={this.props.user.password}
onChangeText={input => this.props.setPassword(input)}
secureTextEntry={true}
/>
<Text style={styles.mainText}>
USERNAME
</Text>
<TextInput
style={styles.inputText}
value={this.props.user.username}
onChangeText={input => this.props.setUserName(input)}
/>
<Text style={styles.mainText}>
FULL NAME
</Text>
<TextInput
style={styles.inputText}
value={this.props.user.fullname}
onChangeText={input => this.props.setFullName(input)}
/>
<TouchableOpacity
style={styles.buttonLighGray}
onPress={() => this.onPress()}>
<Text style={styles.buttonDarkText}>
Accept & Sign Up
</Text>
</TouchableOpacity>
</KeyboardAvoidingView>
</SafeAreaView>
);
}
}
const mapState = (state) => ({
user: state.user,
})
const mapDispatch = (dispatch) => ({
setEmail: mail => dispatch.user.email(mail),
setPassword: pass => dispatch.user.password(pass),
setUserName: usern => dispatch.user.username(usern),
setFullName: fulln => dispatch.user.fullname(fulln),
SignUp: () => dispatch.user.signup(),
})
export default connect(mapState, mapDispatch)(Signup)
Screen.js
import * as React from 'react';
import {
View,
TextInput,
Alert,
Text,
KeyboardAvoidingView,
SafeAreaView,
TouchableOpacity,
}
from 'react-native';
import styles from '../styles'
import { connect } from 'react-redux';
import { Image } from 'react-native-elements';
import '#expo/vector-icons';
import 'redux';
import firebase from 'firebase'
class Screen extends React.Component {
render() {
return (
<SafeAreaView style={styles.container}>
<Text> Full Name: {this.props.user.fullName}</Text>
<Text> Email: {this.props.user.email}</Text>
<Text> username: {this.props.user.username}</Text>
<Text> bio: {this.props.user.bio}</Text>
<Text> gender: {this.props.user.gender}</Text>
<Text> phoneNum: {this.props.user.phoneNum}</Text>
<Text> profilePic: {this.props.user.profilePic}</Text>
</SafeAreaView>
);
}
}
const mapState = (state) => ({
user: state.user,
})
const mapDispatch = (dispatch) => ({
setEmail: mail => dispatch.user.email(mail),
setPassword: pass => dispatch.user.password(pass),
setUserName: usern => dispatch.user.username(usern),
setFullName: fulln => dispatch.user.fullname(fulln),
})
export default connect(mapState, mapDispatch)(Screen)
The problem is that you are returning the current state again in the login reducer. (you declared is at user data)
login(state, payload) {
return {
...state,
...payload
}
// this will take the global state and overwrite everything that is in payload (merge both objects
},
else you could just do just return payload but this could overwrite other stored values in the future!

react navigation "navigate" function not working inside firebase Asynchronous login function

I'm following the famous tutorial of "the-complete-react-native-and-redux-course",
i'm implementing react-navigation with redux and firebase, my problem is that its using the obsolete "react-native-router-flux" approach, i tried to follow it, but the project is not building at all.
I tried to migrate it step by step the the official react-navigation, the problem is, when trying to navigate from inside Asynchronous function (like firebase login function), navigation is not working, (putting in mind that i'm using redux)
**Update: Solution found, below is working code:
here is my Asynchronous function code (inside actions.js):
import firebase from 'firebase';
import { NavigationActions } from 'react-navigation'
import {
EMAIL_CHANGED,
PASSWORD_CHANGED,
LOGIN_USER_SUCCESS,
LOGIN_USER_FAIL,
LOGIN_USER
} from './types';
export const emailChanged = (text) => {
return {
type: EMAIL_CHANGED,
payload: text
};
};
export const passwordChanged = (text) => {
return {
type: PASSWORD_CHANGED,
payload: text
};
};
export const loginUser = ({email, password}, NavigationActions) => {
return (dispatch) => {
//indicate start user log in process
dispatch({type: LOGIN_USER});
firebase.auth().signInWithEmailAndPassword(email,password)
.then(user => loginUserSuccess(dispatch, user, NavigationActions))
.catch(() => {
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(user => loginUserSuccess(dispatch, user, NavigationActions))
.catch(() => loginUserFail(dispatch));
});
};
};
const loginUserFail = (dispatch) => {
dispatch({type: LOGIN_USER_FAIL});
}
const loginUserSuccess = (dispatch, user, NavigationActions) => {
dispatch({
type: LOGIN_USER_SUCCESS,
payload: user,
});
NavigationActions.navigate({ routeName: 'employeeList' })
};
and my router file:
import React from 'react';
import { StackNavigator } from 'react-navigation';
import LoginForm from './components/LoginForm';
import EmployeeList from './components/EmployeeList';
const Router = StackNavigator({
login: { screen: LoginForm },
employeeList: {screen: EmployeeList },
},
{
initialRouteName: 'login',
});
export default Router;
and App.js :
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import reducers from './reducers';
import firebase from 'firebase';
import ReduxThunk from 'redux-thunk';
//import LoginForm from './components/LoginForm';
import Router from './Router';
class App extends Component {
componentWillMount(){
const config = {
apiKey: "AIzaSyDV_vLg656D36E8T9GVraA6ZmZrcUi2QH4",
authDomain: "XXXXXXXXXX.firebaseapp.com",
databaseURL: "https://XXXXXXXXX.firebaseio.com",
projectId: "manager-ba44d",
storageBucket: "manager-ba44d.appspot.com",
messagingSenderId: "200262066369"
};
firebase.initializeApp(config);
}
render() {
const store= createStore(reducers, {}, applyMiddleware(ReduxThunk));
return (
<Provider store={store}>
<Router />
</Provider>
);
}
}
export default App;
my login component that calls the Asynch function:
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import { connect } from 'react-redux';
import { emailChanged, passwordChanged, loginUser } from '../actions';
import { Card, CardSection, Input, Button, Spinner } from './common';
class LoginForm extends Component {
static navigationOptions = () => ({
title: 'Login screen',
headerTitleStyle: {
textAlign:"center",
flex:1
}
});
onEmailChange(text){
this.props.emailChanged(text);
}
onPasswordChange(text){
this.props.passwordChanged(text);
}
onButtonPress(){
const {email, password, navigation} = this.props;
this.props.loginUser({email, password}, navigation);
}
renderError(){
if(this.props.error){
return(
<View style={{backgroundColor: 'white'}}>
<Text style={styles.errorTextStyle}>
{this.props.error}
</Text>
</View>
)
}
}
renderButton(){
if(this.props.loading){
return <Spinner size="large" />;
}
return (
<Button
style={styles.buttonStyle}
buttonText="Login" onPress={this.onButtonPress.bind(this)}>
</Button>
);
}
render(){
return(
<Card>
<CardSection>
<Input
label="Email"
placeholder="email#gmail.com"
onChangeText={this.onEmailChange.bind(this)}
value={this.props.email}
/>
</CardSection>
<CardSection>
<Input
secureTextEntry
label="password"
placeholder="password"
onChangeText={this.onPasswordChange.bind(this)}
value={this.props.password}
/>
</CardSection>
{this.renderError()}
<CardSection>
{this.renderButton()}
</CardSection>
</Card>
);
}
}
const mapStateToProps = state => {
return {
email: state.auth.email,
password: state.auth.password,
error: state.auth.error,
loading: state.auth.loading
};
};
export default connect(mapStateToProps,
{
emailChanged,
passwordChanged,
loginUser
})(LoginForm);
const styles = {
errorTextStyle: {
fontSize: 20,
alignSelf: 'center',
color: 'red'
},
buttonStyle:{
flex: 1,
flexDirection: 'row',
alignSelf: 'stretch'
}
}
UPDATE
You need to import NavigationActions like this
import { NavigationActions } from 'react-navigation'
export const loginUser = ({email, password}, navigation) => {
return (dispatch) => {
//indicate start user log in process
dispatch({type: LOGIN_USER});
firebase.auth().signInWithEmailAndPassword(email,password)
.then(user => loginUserSuccess(dispatch, user))
.then(NavigationActions.navigate('employeeList'))
.catch(() => {
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(user => loginUserSuccess(dispatch, user, navigation))
.catch(() => loginUserFail(dispatch));
});
};
};
const loginUserFail = (dispatch) => {
dispatch({type: LOGIN_USER_FAIL});
}
const loginUserSuccess = (dispatch, user, navigation) => {
dispatch({
type: LOGIN_USER_SUCCESS,
payload: user,
});
NavigationActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: 'employeeList' })],
}),
};

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