i can't connect redux with react-native app - react-native

I have a problem with redux and react-native because I can't connect the state of the "login" view.
I would like to upload the user data and the token in the store.
In "AppState" View, I manage the actions :
import * as type from "../redux/actionTypes";
import {initialState} from "../redux/initialState";
export default function LoginStateReducer(state = initialState, action) {
switch( action.type ) {
case type.SET_LOGIN_STATE:
return {
...state,
user: action.user,
token: action.token,
isLoading: false,
isLoggedIn: true,
};
case type.SET_LOGOUT_STATE:
return {
...state,
user: null,
token: null,
isLoading: false,
isLoggedIn: false,
};
default:
return state;
}
};
In "AppView", I manage the state :
import React, { useState, useEffect, useReducer, useMemo } from 'react';
import { View, ActivityIndicator } from 'react-native';
import AsyncStorage from '#react-native-async-storage/async-storage';
import Login from './login/LoginViewContainer';
import { AuthContext } from './config/Context';
import * as type from '../redux/actionTypes'
import { initialState } from '../redux/initialState';
import LoginStateReducer from './AppState';
import Navigator from './navigation/Navigator';
const App = () => {
const [isLoading, setIsLoading] = useState(true);
const [loginState, dispatch] = useReducer(LoginStateReducer, initialState);
const authContext = useMemo(() => ({
signIn: async(data) => {
setIsLoading(false);
const token = String(data.token);
const user= data.user;
try {
await AsyncStorage .setItem('token', token);
} catch(e) {
console.log(e);
}
dispatch({ type: type.SET_LOGIN_STATE, user: user, token: token });
},
signOut: async() => {
setIsLoading(false);
try {
await AsyncStorage .removeItem('token');
} catch(e) {
console.log(e);
}
dispatch({ type: type.SET_LOGOUT_STATE });
},
}), []);
if( loginState.isLoading ) {
return(
<View style={{flex:1,justifyContent:'center',alignItems:'center'}}>
<ActivityIndicator size="large" />
</View>
);
}
return (
<AuthContext.Provider value={authContext}>
{ loginState.token !== null ? (
<Navigator onNavigationStateChange={() => {}} uriPrefix="/app" />
)
:
<Login />
}
</AuthContext.Provider>
);
}
export default App;
In "AppViewContainer", I connect the reducer with the state :
import { connect } from 'react-redux';
import { compose, lifecycle } from 'recompose';
import { Platform, UIManager } from 'react-native';
import AppView from './AppView';
import LoginStateReducer from './AppState';
export default compose(
connect(
state => ({
user: state.user,
token: state.token,
}),
dispatch => ({
LoginStateReducer: () => dispatch(LoginStateReducer()),
})
),
lifecycle({
componentDidMount() {
if (Platform.OS === 'android') {
UIManager.setLayoutAnimationEnabledExperimental &&
UIManager.setLayoutAnimationEnabledExperimental(true);
}
this.props.LoginStateReducer();
},
}),
)(AppView);
In the "reducer", I have :
import { combineReducers } from 'redux';
// ## Generator Reducer Imports
import LoginStateReducer from '../modules/AppState';
export default combineReducers({
login: LoginStateReducer,
});
When I call the store once connected, it has not changed and I don't understand why :
"login": {"isLoading": true, "isLoggedIn": false, "token": "", "user": ""}
Can you tell me if i am missing something?
Thank you in advance for your feedback

Related

TypeError: undefined is not an object (evaluating 'loginState.isLoading')

I am trying to authenticate a login using Async Storage with React Native. Every time I click on the SignUp button in my simulator it throws me a type error saying "TypeError: undefined is not an object (evaluating 'loginState.isLoading')". I believe the problem is how I'm defining loginState. Here is the page where I define loginState below:
import 'react-native-gesture-handler';
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet,Component, Text,TouchableWithoutFeedback, View,Image,SafeAreaView, Button, ScrollView, ActivityIndicator } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import MainTabScreen from './screens/MainTab';
import {DrawerContent} from './screens/DrawerContent';
import RootStackScreen from './screens/RootStack'
import { useEffect } from 'react';
//import { firebaseConfig } from './screens/config';
import { AuthContext } from './components/context';
import AsyncStorage from '#react-native-async-storage/async-storage';
const Drawer = createDrawerNavigator();
function App() {
// const [isLoading, setIsLoading] = React.useState(true);
// const [userToken, setUserToken] = React.useState(null);
const initialLoginState = {
isLoading: true,
userName: null,
userToken: null,
};
const loginReducer = (prevState, action) => {
switch( action.type ) {
case 'RETRIEVE_TOKEN':
return {
...prevState,
userToken: action.token,
isLoading: false,
};
case 'LOGIN':
return {
...prevState,
userName: action.id,
userToken: action.token,
isLoading: false,
};
case 'LOGOUT':
return {
...prevState,
userName: null,
userToken: null,
isLoading: false,
};
case 'REGISTER':
return {
...prevState,
userName: action.id,
userToken: action.token,
isLoading: false,
};
}
};
const [loginState, dispatch] = React.useReducer(loginReducer, initialLoginState);
const authContext = React.useMemo(() => ({
signIn: (userName,password) =>{
// setUserToken('tony');
// setIsLoading(false);
let userToken;
userToken = null;
if (userName == 'user' && password == 'pass'){
userToken = 'lexi';
}
dispatch({type:'LOGIN,',id:userName, token:userToken});
},
signOut: () => {
// setUserToken(null);
// setIsLoading(false);
dispatch({type:'LOGOUT'});
},
signUp: () => {
setUserToken('tony');
setIsLoading(false);
},
}),[])
useEffect(() => {
setTimeout(() => {
// setIsLoading(false);
dispatch({type:'RETRIEVE_TOKEN',token:'mario'});
},1000);
},[]);
if (loginState.isLoading == true)
{
return(
<View style = {{flex:1,justifyContent:'center',alignItems:'center'}}>
<ActivityIndicator size = "large"/>
</View>
);
}
return (
<AuthContext.Provider value = {authContext}>
<NavigationContainer>
{loginState.userToken !== null ? (
<Drawer.Navigator drawerContent = {props => <DrawerContent {... props}/>}>
<Drawer.Screen name="HomeDrawer" component={MainTabScreen} />
</Drawer.Navigator>
)
:
<RootStackScreen/>
}
</NavigationContainer>
</AuthContext.Provider>
);
}
export default App;
Found the error. I changed:
dispatch({type:'LOGIN,',id:userName, token:userToken});
To:
dispatch({type:'LOGIN',id:userName, token:userToken});

Connect react-redux to stateless component. Properties inside the function are not updated

Problem:
I have very simple todo app. There is one action - add todo. When I add a task, I simulate sending it to the server using a setTimeout.
When I receive a response from the server, I immediately check to see if there is an error to avoid further action. In stateful component, everything works, and in stateless component it doesn't.
See the code to better understand the problem.
Environment:
"react": "16.8.6",
"react-native": "0.60.5",
"react-redux": "^7.1.1",
"redux": "^4.0.4",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.3.0"
№ 1. Stateful component:
import React, {Component} from 'react';
import {View, Button, ActivityIndicator} from 'react-native';
import {connect} from 'react-redux';
import {addTodo as addTodoAction} from '../redux/reducer';
class MainScreen extends Component {
todoGenerator = () => ({
id: new Date().getTime(),
text: 'Pls help me ' + new Date().getTime(),
});
sendTodoToServer = async () => {
const todo = this.todoGenerator();
const {addTodo} = this.props;
await addTodo(todo);
// this
const {error} = this.props;
if (error) {
console.log('error', error);
}
};
render() {
const {isLoading} = this.props;
return (
<View>
<Button title="Generate todo" onPress={this.sendTodoToServer} />
{isLoading && <ActivityIndicator />}
</View>
);
}
}
export default connect(
state => ({
todos: state.todos,
error: state.error,
isLoading: state.isLoading,
}),
{
addTodo: addTodoAction,
},
)(MainScreen);
№ 1. Stateful component. Console:
As you can see,
const {error} = this.props;
if (error) {
console.log('error', error);
}
it's work. Okay, let's move on to functional components
№ 2. Stateless component with redux connect:
import React from 'react';
import {ActivityIndicator, Button, View} from 'react-native';
import {connect} from 'react-redux';
import {addTodo as addTodoAction} from '../redux/reducer';
const MainScreenFC = ({isLoading, addTodo, error}) => {
const todoGenerator = () => ({
id: new Date().getTime(),
text: 'Pls help me ' + new Date().getTime(),
});
const sendTodoToServer = async () => {
const todo = todoGenerator();
await addTodo(todo);
if (error) {
console.log('error', error);
}
};
return (
<View>
<Button title="Generate todo" onPress={sendTodoToServer} />
{isLoading && <ActivityIndicator />}
</View>
);
};
export default connect(
state => ({
todos: state.todos,
error: state.error,
isLoading: state.isLoading,
}),
{
addTodo: addTodoAction,
},
)(MainScreenFC);
№ 2. Stateless component with redux connect. Console:
The error did not display in the console, although it is in the reducer
№ 3. Stateless component with redux HOOKS:
import React from 'react';
import {ActivityIndicator, Button, View} from 'react-native';
import {connect, shallowEqual, useDispatch, useSelector} from 'react-redux';
import {addTodo as addTodoAction} from '../redux/reducer';
const MainScreenReduxHooks = () => {
const todos = useSelector((state: AppState) => state.todos, shallowEqual);
const error = useSelector((state: AppState) => state.error, shallowEqual);
const isLoading = useSelector(
(state: AppState) => state.isLoading,
shallowEqual,
);
const dispatch = useDispatch();
const todoGenerator = () => ({
id: new Date().getTime(),
text: 'Pls help me ' + new Date().getTime(),
});
const sendTodoToServer = async () => {
const todo = todoGenerator();
await dispatch(addTodoAction(todo));
if (error) {
console.log('error', error);
}
};
return (
<View>
<Button title="Generate todo" onPress={sendTodoToServer} />
{isLoading && <ActivityIndicator />}
</View>
);
};
export default connect(
state => ({
todos: state.todos,
error: state.error,
isLoading: state.isLoading,
}),
{
addTodo: addTodoAction,
},
)(MainScreenReduxHooks);
№ 3. Stateless component with redux HOOKS. Console:
It's the same here, as in the second example.
Questions:
Can redux be connected to a stateless component?
How do you make the second and third example work the same way as the first?
Other code:
App.js
import React from 'react';
import {Provider} from 'react-redux';
import {MainScreen, MainScreenFC, MainScreenReduxHooks} from './src/screens';
import store from './src/redux';
const App = () => {
return (
<Provider store={store}>
<MainScreenFC />
</Provider>
);
};
export default App;
store.js:
import {applyMiddleware, createStore} from 'redux';
import thunk from 'redux-thunk';
import logger from 'redux-logger';
import rootReducer from './reducer';
export default createStore(rootReducer, applyMiddleware(thunk, logger));
reducer.js:
const ADD_TODO_REQUEST = 'ADD_TODO_REQUEST';
const ADD_TODO_SUCCESS = 'ADD_TODO_SUCCESS';
const ADD_TODO_FAILURE = 'ADD_TODO_FAILURE';
const initialState = {
todos: [],
isLoading: false,
error: undefined,
};
export const addTodo = data => async dispatch => {
dispatch({
type: ADD_TODO_REQUEST,
payload: {
isLoading: true,
},
});
try {
const todo = await new Promise((resolve, reject) => {
setTimeout(() => {
reject('Ooops, error');
}, 3000);
});
dispatch({
type: ADD_TODO_SUCCESS,
payload: {
todo,
isLoading: false,
},
});
} catch (e) {
dispatch({
type: ADD_TODO_FAILURE,
payload: {
isLoading: false,
error: e,
},
});
}
};
export default function(state = initialState, {type, payload}) {
switch (type) {
case ADD_TODO_REQUEST: {
return {
...state,
isLoading: true,
};
}
case ADD_TODO_SUCCESS: {
return {
...state,
isLoading: false,
todos: [...state.todos, payload.todo],
};
}
case ADD_TODO_FAILURE: {
return {
...state,
isLoading: false,
error: payload,
};
}
default:
return state;
}
}
I think the problem with your code is that you try to wait for a response in the component, it's a bad idea for both stateful and stateless components. What would I recommend you to do, is to handle error somewhere in your middleware (redux-thunk, redux-saga, etc). In this case, your component should just represent data, and if you have to display an error, just take it from props, I believe it is stored somewhere in redux.
In any way, stateless components shouldn't be an async function, because the result of an async function is a promise but not a component. There are some libraries like async-reactor, but personally, I prefer to go with another approach.
If you tell me your use case, what would you like to do once you got an error, I'll give you a more useful answer.
Update:
export const addTodo = data => dispatch => {
// tell your application that request is sending,
// so you can handle it in UI (show a progress indicator)
dispatch({
type: ADD_TODO_REQUEST,
payload: data
});
try {
const response = await createTodo(data);
dispatch({
type: ADD_TODO_SUCCESS,
payload: response
});
// here you can dispatch navigation action as well
} catch (error) {
dispatch({
type: ADD_TODO_FAILURE,
error
});
// and here you can dispatch action with a toast
// to notify users that something went wrong
}
};

mapStateToProps does not re-render the component after state change

I've been working with React/React-Native for a while now, but I'm new to Redux and I cannot find the problem. I have a RESTFull API and two main modules: the service model and the price model. Once the admin user adds a new service the user can also associate a price for that service. The problema is that when I add a service (in the NewServiceScreen) my code dispatches an action to change the redux store and therefore update the service list on the NewPriceScreen for the user to associate a price with the service that was just added.
NewPriceScreen.js
function mapStateToProps(state){
return {
newPrice: state.newPriceReducer
}
}
// Exports the connected NewPriceScreen
export default connect(mapStateToProps)(NewPriceScreen);
NewServiceScreen
...
handleSubmit = async() => {
const { descricao } = this.props.newService;
const userToken = await AsyncStorage.getItem('token');
axios.post('/estabelecimento/servicos/',{descricao: descricao}, {
headers: {
"Authorization": `Token ${userToken}`
}
})
.then(res => {
Alert.alert(
'Deu tudo certo :)',
'Dados salvos com sucesso !',
);
console.log(res.data);
this.props.dispatch({type: 'addService', newService: res.data});
})
.catch(error =>{
Alert.alert(
'Ops ! Algo aconteceu :(',
error.message,
);
})
}
...
const mapStateToProps = state => ({
newService: state.newService
});
export default connect(mapStateToProps)(NewServiceScreen);
Reducers.js
const initialState = {
servicos: [],
// Database variables
servico: 0,
duracao: '',
custo: '',
comissao: ''
}
export default function newPriceReducer(state = initialState, action){
// console.log("My state")
// console.log(state);
switch(action.type){
case 'setState': {
return {
...state,
servico: action.descricao,
duracao: action.duracao,
custo: action.custo,
comissao: action.comissao
}
}
case "ADD_SERVICES": {
// console.log("Servicos");
const newState = {
...state,
servicos: action.servicos
}
// console.log(newState);
// console.log(newState === initialState)
return newState;
}
case 'addService': {
// console.log("ADD Service");
servicos = state.servicos;
servicos.push(action.newService);
const newState = {
...state,
servicos: servicos
}
// console.log(newState);
// console.log(newState === initialState);
return newState
}
default:
return state;
}
}
const initialState = {
descricao: ''
}
export default function newServiceReducer(state = initialState, action){
switch(action.type){
case 'setDescricao': {
return {
...state,
descricao: action.descricao
}
}
default:
return state;
}
}
App.js
import { createStore, applyMiddleware, combineReducers } from "redux";
import thunkMiddleware from 'redux-thunk'
import newServiceReducer from '../reducers/NewService';
import newPriceReducer from "../reducers/NewPrice";
import logger from 'redux-logger';
const mainReducer = combineReducers({
newService: newServiceReducer,
newPriceReducer
})
const store = createStore(mainReducer, applyMiddleware(logger));
export default store
import React from 'react';
import { Platform, StatusBar, StyleSheet, View, AsyncStorage, ImageBackground} from 'react-native';
import { AppLoading, Asset, Font, Icon } from 'expo';
import AppNavigator from './navigation/AppNavigator';
// Redux Stuff
import {Provider} from 'react-redux';
import AppStore from './store/App';
export default class App extends React.Component {
state = {
isLoadingComplete: false,
isLoggedIn: false,
};
render() {
if (!this.state.isLoadingComplete && !this.props.skipLoadingScreen) {
return (
<AppLoading
startAsync={this._loadResourcesAsync}
onError={this._handleLoadingError}
onFinish={this._handleFinishLoading}
/>
);
} else {
return (
<Provider store={AppStore}>
<ImageBackground source={require('./assets/images/back.png')} style={{width: '100%', height: '100%'}}>
{Platform.OS === 'ios' && <StatusBar barStyle="default" />}
<AppNavigator />
</ImageBackground>
</Provider>
);
}
}
}
In lines:
servicos = state.servicos;
servicos.push(action.newService);
I was making some sort mutation. I just changed it to:
const newState = {
...state,
servicos: [...state.servicos, action.newService]
}

Unrecognized font family 'entypo'

I'm using the create react native app by the expo team to build an app. Using Icon component from react-native-elements to create a react navigation header feature. Snippet below:
const Navigator = new createStackNavigator({
Home: {
screen: Home,
path: '/',
navigationOptions: ({ navigation }) => ({
title: 'Home',
headerStyle: {
backgroundColor: 'black'
},
headerLeft: (
<Icon
name="menu"
size={30}
type="entypo"
style={{ paddingLeft: 10 }}
/>
),
}),
},
})
I encountered this error:
After numerous iterations, I found this supposed work around 1st and 2nd by the expo team and implemented it this way below for the app but still encountering the same problems.
import Expo from "expo";
import React from 'react';
import { Platform, StatusBar, StyleSheet, View } from 'react-native';
import { AppLoading, Asset, Font } from 'expo';
import { FontAwesome, Ionicons } from '#expo/vector-icons';
import { connect } from 'react-redux'
import { Auth } from 'aws-amplify';
import AuthTabs from './auth/Tabs';
import Nav from './navs/Navigator';
import Home from "./components/Home";
class App extends React.Component {
state = {
user: {},
isLoading: true,
isLoadingComplete: false,
};
async componentDidMount() {
StatusBar.setHidden(true)
try {
const user = await Auth.currentAuthenticatedUser()
this.setState({ user, isLoading: false })
} catch (err) {
this.setState({ isLoading: false })
}
}
async componentWillReceiveProps(nextProps) {
try {
const user = await Auth.currentAuthenticatedUser()
this.setState({ user })
} catch (err) {
this.setState({ user: {} })
}
}
render() {
if (!this.state.isLoadingComplete && !this.props.skipLoadingScreen) {
return(
<AppLoading
startAsync={this._loadResourcesAsync}
onError={this._handleLoadingError}
onFinish={this._handleFinishLoading}
/>
);
}
else{
if (this.state.isLoading) return null
let loggedIn = false
if (this.state.user.username) {
loggedIn = true
}
if (loggedIn) {
return (
<Nav />
)
}
return (
<AuthTabs />
)
}
}
_loadResourcesAsync = async () => {
console.log("fonts loading..")
const entypoFont = {
'entypo': require('../node_modules/#expo/vector-icons/fonts/Entypo.ttf')
};
const fontAssets = cacheFonts([ FontAwesome.font, Ionicons.font, entypoFont ]);
console.log("loaded all fonts locally")
await Promise.all([...fontAssets]);
console.log("promisified all fonts")
};
_handleLoadingError = error => {
console.warn(error);
};
_handleFinishLoading = () => {
this.setState({ isLoadingComplete: true });
};
}
function cacheFonts(fonts){
return fonts.map(font => Font.loadAsync(font))
}
const mapStateToProps = state => ({
auth: state.auth
})
export default connect(mapStateToProps)(App)
What are my doing wrong and how can it be configured appropriately? Thank you

React-Native/React navigation redirection after login with redux

I have a problem during the login my redirection is not done, I use a rail API for the back, I can recover the user, but when I click on login the page reloads and does not navigate on the home screen.
In my AuthActions.js after the dispatch I added NavigationActions.navigate ('Home'), this should allow me to go to the home page
AppNavigator.js
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { addNavigationHelpers, StackNavigator, TabNavigator } from 'react-navigation';
import { addListener } from '../../utils/redux';
import LoginScreen from '../login/LoginForm';
import RegisterScreen from '../register/RegisterForm';
import LogoutScreen from '../logout/Logout';
import Home from '../home/HomeList';
import Hair from '../hair/HairList';
export const Tabs = TabNavigator({
screen1: {
screen: Home
}
});
export const AppNavigator = StackNavigator({
Login: { screen: LoginScreen },
Main: { screen: Home },
Hair: { screen: Hair },
},{
initialRouteName : 'Login'
});
class AppWithNavigationState extends React.Component {
static propTypes = {
dispatch: PropTypes.func.isRequired,
nav: PropTypes.object.isRequired,
};
render() {
const { dispatch, nav } = this.props;
return (
<AppNavigator
navigation={addNavigationHelpers({
dispatch,
state: nav,
addListener,
})}
/>
);
}
}
const mapStateToProps = state => ({
nav: state.nav,
});
export default connect(mapStateToProps)(AppWithNavigationState);
AuthReducers.js
import {
EMAIL_CHANGED,
PASSWORD_CHANGED,
LOGIN_USER_SUCCESS,
LOGIN_USER_FAIL,
LOGIN_USER
} from '../actions/types';
const INITIAL_STATE = {
email: '',
password: '',
user: null,
error: '',
loading: false,
};
export default (state = INITIAL_STATE, action) => {
// console.log('action =>', 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: 'Authentication Failed.', password: '', loading: false };
default:
return state;
}
};
// newState === oldState ? nothing : update state, so component too
AuthActions.js
import { NavigationActions } from 'react-navigation';
import Api from '../api';
import User from '../models/User';
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 }) => {
return (dispatch) => {
dispatch({ type: LOGIN_USER });
Api.userSignUp(email, password)
.then((user) => loginUserSuccess(dispatch, user))
.catch((error) => {
console.log(error);
loginUserFail(dispatch);
});
};
};
const loginUserFail = (dispatch) => {
dispatch({
type: LOGIN_USER_FAIL
});
};
const loginUserSuccess = (dispatch, user) => {
// console.log('access token =>', User.getAccessToken());
// Api.createEmployee(null);
dispatch({
type: LOGIN_USER_SUCCESS,
payload: user,
});
NavigationActions.navigate('home'); //HERE NOT REDIRECT AFTER SUCCESS TO HOME
};
LoginForm.js
import React, { Component } from 'react';
import { 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 {
onEmailChange(text) {
this.props.emailChanged(text);
}
onPasswordChange(text) {
this.props.passwordChanged(text);
}
onButtonPress() {
const { email, password } = this.props;
this.props.loginUser({ email, password });
}
renderButton() {
if (this.props.loading) {
return <Spinner size="large" />;
}
return (
<Button onPress={this.onButtonPress.bind(this)}>
Login
</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>
<Text style={styles.errorTextStyle}>
{this.props.error}
</Text>
<CardSection>
{this.renderButton()}
</CardSection>
</Card>
);
}
}
const styles = {
errorTextStyle: {
fontSize: 20,
alignSelf: 'center',
color: 'red'
}
};
const mapStateToProps = ({ auth }) => {
const { email, password, error, loading } = auth;
return { email, password, error, loading };
};
export default connect(mapStateToProps, {
emailChanged, passwordChanged, loginUser
})(LoginForm);
App.js
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import ReduxThunk from 'redux-thunk';
import AppReducer from './reducers';
import AppWithNavigationState from './components/navigator/AppNavigator';
import { middleware } from './utils/redux';
import User from './models/User.js';
import {
NavigationActions,
} from 'react-navigation';
const store = createStore(
AppReducer,
applyMiddleware(ReduxThunk),
);
class App extends Component {
state = { isLoggedIn: null }
componentWillMount() {
// Si le asyncstorage a changé (connexion, etc)
User.getCurrent().then((user) => {
console.log('GetCurrentUser =>', user);
if (user) {
this.setState({isLoggedIn: true});
this.props.navigation.navigate('Main', user);
}
else {
this.setState({isLoggedIn: false});
}
})
}
render() {
return (
<Provider store={store}>
<AppWithNavigationState />
</Provider>
);
}
}
export default App;
I'm blocking for some day on the worries, I still is not finding a solution
use this code NavigationActions.NAVIGATE("home") works for me
You have to use componentWillReceiveProps in your Home like this:
//Home
componentWillReceiveProps(nextProps) {
if(nextProps.user) {
this.props.navigation.navigate('Home');
}
}
LoginForm.js
const mapStateToProps = state => {
return {
error: state.auth.error,
loading: state.auth.loading,
user: state.auth.user,
}
}
And you edit your AuthReducers.js like this:
case LOGIN_USER_SUCCESS:
return { ...state, ...INITIAL_STATE, user: action.user};
It works for me!