I'm building a React Native app, currently trying to implement an authentication registration system through Firebase. here is my whole code.
import React, { Component } from 'react';
import { Platform, StyleSheet, KeyboardAvoidingView, SafeAreaView, View, YellowBox, LogBox, AsyncStorage } from 'react-native';
import { GiftedChat, InputToolbar } from 'react-native-gifted-chat';
import FontAwesomeIcon from 'react-native-vector-icons/FontAwesome';
import AnimatedLoader from "react-native-animated-loader";
import firebaseSDK from "../../firebaseSDK";
import firebase from 'firebase';
import { v4 as uuid } from 'uuid';
LogBox.ignoreLogs(['Setting a timer']);
const customtInputToolbar = props => {
return (
<InputToolbar
{...props}
containerStyle={{
backgroundColor: "white",
borderTopColor: "#E8E8E8",
borderTopWidth: 1,
//padding: 8
}}
/>
);
};
export default class Chat extends Component {
constructor(props) {
super(props);
this.state = {
messages: [],
chatgenidres: '',
}
this.init()
this.checkAuth()
}
init = () => {
if (!firebase.apps.length) {
firebase.initializeApp({
apiKey: "xxxxxxxxxxxxxxxxxxxxxs",
authDomain: "xxxxxxxxxxxxx",
databaseURL: "xxxxxxxxxxxxxxxxxxxx",
projectId: "xxxxxxxxxxx",
storageBucket: "xxxxxxxxxxxx",
messagingSenderId: "xxxxxxxxxxxxx",
appId: "xxxxxxxxxxxxxxxxxx",
measurementId: "xxxxxxxxxxxxx"
})
}
};
checkAuth = () => {
firebase.auth().onAuthStateChanged(user => {
if (!user) {
firebase.auth().signInAnonymously();
}
})
}
send = messages => {
console.log(messages);
messages.forEach(item => {
const message = {
text: item.text,
timestamp: firebase.database.ServerValue.TIMESTAMP,
user: item.user
};
this.db.push(message);
});
};
parse = message => {
const { user, text, timestamp } = message.val();
const { key: _id } = message;
const createdAt = new Date(timestamp);
return {
_id,
createdAt,
text,
user
};
};
get = callback => {
this.db.on("child_added", snapshot => callback(this.parse(snapshot)));
};
off() {
this.db.off();
}
get db() {
console.log(this.state.chatgenidres)
return firebase.database().ref(this.state.chatgenidres)
};
get uid() {
return (firebase.auth().currentUser || {}).uid;
}
get user() {
return {
_id: this.uid,
chatfromusername: this.props.navigation.state.params.chatFromName,
chatfromuserid: this.props.navigation.state.params.chatFromId,
chattouserid: this.props.navigation.state.params.chatToId,
chattousername: this.props.navigation.state.params.chatToName,
}
}
componentDidMount() {
let genId = this.props.navigation.state.params.chatFromId + 'connectedto' + this.props.navigation.state.params.chatToId;
//AsyncStorage.setItem('chatgenid', genId);
AsyncStorage.getItem('chatgenid', (err, chatgenidres) => {
console.log(chatgenidres, 'from chat.js');
this.setState({ chatgenidres: chatgenidres });
this.get(message =>
this.setState(previous => ({
messages: GiftedChat.append(previous.messages, message)
}))
);
});
}
componentWillUnmount() {
this.off();
}
render() {
const chat = <GiftedChat
messages={this.state.messages}
onSend={this.send}
user={this.user}
style={styles.messageContainer}
renderInputToolbar={props => customtInputToolbar(props)}
/>;
if (Platform.OS === 'android') {
return (
<View style={styles.container} behavior="padding" keyboardVerticalOffset={30} enabled>
<View style={{ flexDirection: 'row', padding: 13, justifyContent: 'space-between', alignItems: 'center', backgroundColor: 'rgba(0,0,0,0.1)' }}>
<FontAwesomeIcon name="arrow-left" size={20} onPress={() => { this.props.navigation.goBack() }} color="#FFF" />
</View>
{chat}
</View>
)
}
return <SafeAreaView style={{ flex: 1 }}>{chat}</SafeAreaView>
}
}
but when i run this application i get " FirebaseError: Firebase: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp() (app/no-app)." this error.what is wrong with my code.how to solve this.
Related
If 2 user is using the app, messages are being displayed on the left side of the screen. cannot differentiate between them
here my full code below
import React, { Component } from 'react';
import { Platform, StyleSheet, KeyboardAvoidingView, SafeAreaView, View, YellowBox, LogBox, AsyncStorage } from 'react-native';
import { GiftedChat, InputToolbar } from 'react-native-gifted-chat';
import FontAwesomeIcon from 'react-native-vector-icons/FontAwesome';
import AnimatedLoader from "react-native-animated-loader";
import firebaseSDK from "../../firebaseSDK";
import firebase from 'firebase';
LogBox.ignoreLogs(['Setting a timer']);
const customtInputToolbar = props => {
return (
<InputToolbar
{...props}
containerStyle={{
backgroundColor: "white",
borderTopColor: "#E8E8E8",
borderTopWidth: 1,
//padding: 8
}}
/>
);
};
export default class Chat extends Component {
constructor(props) {
super(props);
this.state = {
messages: [],
chatgenidres: '',
}
this.init()
this.checkAuth()
}
init = () => {
if (!firebase.apps.length) {
firebase.initializeApp({
apiKey: "apiKey",
authDomain: "authDomain",
databaseURL: "databaseURL",
projectId: "projectId",
storageBucket: "storageBucket",
messagingSenderId: "messagingSenderId",
appId: "appId",
measurementId: "measurementId"
})
}
};
checkAuth = () => {
firebase.auth().onAuthStateChanged(user => {
if (!user) {
firebase.auth().signInAnonymously();
}
})
}
send = messages => {
console.log(messages);
messages.forEach(item => {
const message = {
text: item.text,
timestamp: firebase.database.ServerValue.TIMESTAMP,
user: item.user
};
this.db.push(message);
});
};
parse = message => {
const { user, text, timestamp } = message.val();
const { key: _id } = message;
const createdAt = new Date(timestamp);
return {
_id,
createdAt,
text,
user
};
};
get = callback => {
this.db.on("child_added", snapshot => callback(this.parse(snapshot)));
};
off() {
this.db.off();
}
get db() {
console.log(this.state.chatgenidres)
return firebase.database().ref(this.state.chatgenidres)
};
get uid() {
return (firebase.auth().currentUser || {}).uid;
}
get user() {
return {
_id: this.uid,
chatfromusername: this.props.navigation.state.params.chatFromName,
chatfromuserid: this.props.navigation.state.params.chatFromId,
chattouserid: this.props.navigation.state.params.chatToId,
chattousername: this.props.navigation.state.params.chatToName,
}
}
componentDidMount() {
let genId = this.props.navigation.state.params.chatFromId + 'connectedto' + this.props.navigation.state.params.chatToId;
//AsyncStorage.setItem('chatgenid', genId);
AsyncStorage.getItem('chatgenid', (err, chatgenidres) => {
console.log(chatgenidres, 'from chat.js');
this.setState({ chatgenidres: chatgenidres });
this.get(message =>
this.setState(previous => ({
messages: GiftedChat.append(previous.messages, message)
}))
);
});
}
componentWillUnmount() {
this.off();
}
render() {
const chat = <GiftedChat
messages={this.state.messages}
onSend={this.send}
user={this.user}
style={styles.messageContainer}
renderInputToolbar={props => customtInputToolbar(props)}
/>;
if (Platform.OS === 'android') {
return (
<View style={styles.container} behavior="padding" keyboardVerticalOffset={30} enabled>
<View style={{ flexDirection: 'row', padding: 13, justifyContent: 'space-between', alignItems: 'center', backgroundColor: 'rgba(0,0,0,0.1)' }}>
<FontAwesomeIcon name="arrow-left" size={20} onPress={() => { this.props.navigation.goBack() }} color="#FFF" />
</View>
{chat}
</View>
)
}
return <SafeAreaView style={{ flex: 1 }}>{chat}</SafeAreaView>
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#5e5e5e'
},
messageContainer: {
color: 'red'
}
})
But when send one new message at that time message will display separately sender and receiver format. how to differentiate those messages. I use react-native-gifted-chat. but not working properly. I am using react-native-gifted-chat and firebase.
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!
I have a splashscreen in which appears the logo of my app and the title, and I give it a few seconds before doing anything with a setTimeout. Whithin that time I'm trying to check if the user already logged in before in the app or it's new by using this function that firebase has firebase.auth().onAuthStateChanged() which should return an user object with the information about the logged user, or nothing if the user didn't logged in. It detects that I was logged in, for that case I want my app to redirect to the main scene, which was working fine, but now I want to have that user's information in the main scene as well so I tried using this.props.user = user;, but my compiler gave me an error saying this:
TypeError: TypeError: TypeError: null is not an object (evaluating 'elements.props')
What can I do? I thought I could access to my props from componentDidMount function.
The code of my SplashScreen.js
import React, { Component } from 'react';
import { View, Image } from 'react-native';
import TypeWriter from 'react-native-typewriter';
import firebase from 'firebase';
import { Actions } from 'react-native-router-flux';
import { connect } from 'react-redux';
import { reloginUser } from '../actions';
class SplashScreen extends Component {
componentDidMount() {
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: "AIzaSyDSV1Ozhe4M6p9Q9MdUGSCAqhW53DyUNYo",
authDomain: "idionative.firebaseapp.com",
databaseURL: "https://idionative.firebaseio.com",
projectId: "idionative",
storageBucket: "idionative.appspot.com",
messagingSenderId: "924806570373",
appId: "1:924806570373:web:a3f5b6dc190d8039"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
setTimeout(function() {
firebase.auth().onAuthStateChanged((user) => {
if (user) { // Here I check whether the user was logged in or not
this.props.user = user;
Actions.main();
} else {
Actions.auth();
}
});
}, 2000);
}
render() {
const { sceneStyle, logoStyle, titleStyle } = styles;
return(
<View style={sceneStyle}>
<Image source={require('../assets/images/logo.png')} style={logoStyle} />
<TypeWriter typing={1} style={titleStyle}>Idionative{this.props.user}</TypeWriter>
</View>
);
}
}
const styles = {
sceneStyle: {
backgroundColor: '#9ED0E6',
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
logoStyle: {
width: 120,
height: 120
},
titleStyle: {
fontFamily: 'NotoSans-Regular',
fontSize: 50,
color: 'black',
marginTop: 20
}
};
const mapStateToProps = ({ auth }) => {
const { user } = auth;
return { user };
};
export default connect(mapStateToProps, { reloginUser })(SplashScreen);
The code of my actions file:
import firebase from 'firebase';
import { Actions } from 'react-native-router-flux';
import { EMAIL_CHANGED, PASSWORD_CHANGED, LOGIN_USER_SUCCESS, LOGIN_USER_FAIL, LOGIN_USER, RELOGIN_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 }) => {
return (dispatch) => {
dispatch({ type: LOGIN_USER });
firebase.auth().signInWithEmailAndPassword(email, password)
.then(user => loginUserSuccess(dispatch, user))
.catch(() => loginUserFail(dispatch));
}
}
export const reloginUser = (user) => {
return {
type: RELOGIN_USER,
payload: user
};
};
const loginUserSuccess = (dispatch, user) => {
dispatch({
type: LOGIN_USER_SUCCESS,
payload: user
});
Actions.main();
};
const loginUserFail = (dispatch) => {
dispatch({
type: LOGIN_USER_FAIL
});
};
My reducer file:
import { EMAIL_CHANGED, PASSWORD_CHANGED, LOGIN_USER_SUCCESS, LOGIN_USER_FAIL, LOGIN_USER, RELOGIN_USER } from '../actions/types';
const INITIAL_STATE = { email: '', password: '', user: null, error: '', loading: false };
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case EMAIL_CHANGED:
return { ...state, email: action.payload };
case PASSWORD_CHANGED:
return { ...state, password: action.payload };
case LOGIN_USER:
return { ...state, loading: true, error: '' }
case LOGIN_USER_SUCCESS:
return { ...state, ...INITIAL_STATE, user: action.payload, };
case LOGIN_USER_FAIL:
return { ...state, error: 'This User Does Not Exist', password: '', loading: false }
case RELOGIN_USER:
return { ...state, user: action.payload }
default:
return state;
}
};
How to declare an array on a state variable
Im using react native expo and firebase all is up to date
export default class Profile extends Component {
state = {
ageRangeValues: this.props.user.ageRange,
distanceValue: [this.props.user.distance],
}
render() {
const {
ageRangeValues,
distanceValue,
} = this.state;
return (
<View>
<Slider
min={5}
max={100}
values={distanceValue}
onValuesChange={val => this.setState({ distanceValue: val })}
onValuesChangeFinish={val => this.updateUser('distance', val[0])}
/>
<Slider
min={18}
max={70}
values={ageRangeValues}
onValuesChange={val => this.setState({ ageRangeValues: val })}
onValuesChangeFinish={val => this.updateUser('ageRange', val)}
/>
</View>) }
I expect this to work fine but the ageRangeValue is undefined but the distanceValue in defined don't know why may be is because ageRangeValue takes ageRange and its an Array. If I declare areRangeValue: [19, 20], everything works, but if I left it the way it is all my values are undefined
and here is my preload
const firebaseConfig = {
apiKey: 'XXXXXXXXX',
databaseURL: 'XXXXX',
storageBucket: 'XXXXX',
};
firebase.initializeApp(firebaseConfig);
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
width: null,
height: null,
resizeMode: 'contain',
},
});
export default class Preload extends Component {
constructor() {
super();
this.loadApp();
// SVGAnimatedLengthList.loadApp();
}
authenticate = (token) => {
const provider = firebase.auth.FacebookAuthProvider
const credential = provider.credential(token);
return firebase.auth().signInWithCredential(credential);
};
_goHome = (user) => {
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: 'Home', params: { user } })],
});
this.props.navigation.dispatch(resetAction);
};
loadApp = async () => {
//firebase.auth().signOut();
firebase.auth().onAuthStateChanged((auth) => {
if (auth) {
this.firebaseRef = firebase.database().ref('users');
this.firebaseRef.child(auth.uid).on('value', (snap) => {
const user = firebase.auth().currentUser;
if (user != null) {
this.firebaseRef.child(auth.uid).off('value');
this._goHome(user);
}
});
} else {
this.setState({ showSpinner: false });
this.props.navigation.navigate('Login');
}
});
}
render() {
return (
<ImageBackground source={require('./images/fondo.png')} style={styles.container}>
<ActivityIndicator />
</ImageBackground>
);
}
}
Try it with constructor
export default class Profile extends Component {
constructor(){
super();
this.state = {
ageRangeValues: this.props.user.ageRange,
distanceValue: [this.props.user.distance],
};
}
render() {
const { ageRangeValues, distanceValue } = this.state;
return (
<View>
<Slider
min={5}
max={100}
values={distanceValue}
onValuesChange={val => this.setState({ distanceValue: val })}
onValuesChangeFinish={val => this.updateUser('distance', val[0])}
/>
<Slider
min={18}
max={70}
values={ageRangeValues}
onValuesChange={val => this.setState({ ageRangeValues: val })}
onValuesChangeFinish={val => this.updateUser('ageRange', val)}
/>
</View>
);
}
Vencovsky was right on the previews page that pass the data
loadApp = async () => {
//firebase.auth().signOut();
firebase.auth().onAuthStateChanged((auth) => {
if (auth) {
this.firebaseRef = firebase.database().ref('users');
this.firebaseRef.child(auth.uid).on('value', (snap) => {
const user = firebase.auth().currentUser;
if (user != null) {
this.firebaseRef.child(auth.uid).off('value');
this._goHome(user);
}
});
} else {
this.setState({ showSpinner: false });
this.props.navigation.navigate('Login');
}
});
}
Changing const user = firebase.auth().currentUser; to const user = snap.val();
made the trick
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?