houman.sanati
houman.sanati

Reputation: 1074

React Redux is not updating the state

I am searching for a couple of days and I can't find out why redux is not updating the state I don't see any problem in my code please help me to find the problem.

it is a simple login project. I can see that data changes inside the reducer when debugging but it's not being mapped to props and state is not changing.

this is my code:

actions.js

import {
    LOGIN_SUCCESS,
    LOGIN_FAILURE,
} from './types'

export const loginSuccess = (user) => ({
    type: LOGIN_SUCCESS,
    payload: user
})

export const loginFailure = (error) => ({
    type: LOGIN_FAILURE,
    payload: error
})

loginReducer.js

import {
    LOGIN_SUCCESS,
    LOGIN_FAILURE,
} from './types'

const initialState = {
    user: null,
    errorMessage: null
}


export const loginReducer = (state = initialState, action) => {
    switch (action.type) {
        case LOGIN_SUCCESS:
            return {...state,user: action.payload, errorMessage: null }
        case LOGIN_FAILURE:
            return {...state,errorMessage: action.payload }
        default:
            return state;
    }
}

loginScreen.js

import React from 'react'
import {
    Text,
    View,
    ImageBackground,
    Button,
    StyleSheet
} from 'react-native'
import { TextField } from 'react-native-material-textfield';
import { loginSuccess, loginFailure } from './reduxx/actions'
import { connect } from "react-redux";

class LoginScreen extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            email: "",
            password: "",
        }
    }

    _handlePress() {
        this.props.login(this.state.email, this.state.password)

        // user in propa is undifined 
        this.props.user
    }

    render() {

        let { email, password } = this.state

        return (
            <ImageBackground source={require('./images/loginBackground.jpg')} style={styles.imageBackground}>
                <View style={styles.mainContainer}>
                    <View style={styles.box}>
                        <TextField label="Email" value={email} onChangeText={email => this.setState({ email })} />
                        <TextField label="Password" textContentType="password" value={password} onChangeText={password => this.setState({ password })} />
                        <Button onPress={() => {

                            this._handlePress()

                        }} color="green" title="Sign in" style={styles.button} />
                    </View>

                    <View style={styles.bottomTextContainer}>
                        <Text style={{ color: "white" }}>Don't have an account?</Text>
                        <Text style={{ color: "lightgreen" }} onPress={() => this.props.navigation.navigate("Register")}> Sign up</Text>
                    </View>
                </View>
            </ImageBackground>
        )
    }
}

function mapStateToProps(state) {
    return {
        user: state.user,
        errorMessage: state.errorMessage
    }
}

function mapDispatchToProps(dispatch) {
    return {
        login: (email, password) => {
            try {
                let user = //get user from database
                dispatch(loginSuccess(user))
            } catch (error) {
                dispatch(loginFailure(error))
            }
        },
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(LoginScreen);

const styles = StyleSheet.create({
    imageBackground: {
        width: '100%',
        height: '100%'
    },
    mainContainer: {
        flex: 1,
        justifyContent: "center"
    },
    box: {
        backgroundColor: 'white',
        padding: 8,
        margin: 8
    },
    button: {
        margin: 10
    },
    bottomTextContainer: {
        position: "absolute",
        bottom: 8,
        alignSelf: "center",
        flexDirection: "row"
    }
});

app.js

import React from 'react';
import { Provider } from "react-redux"
import store from "./reduxx/store";
import AppContainer from './Navigator'

export default class App extends React.Component {

  render() {
    return (
      <Provider store={store} >
        <AppContainer />
      </Provider>
    );
  }
}

store.js

import {createStore} from "redux";
import { combineReducers } from 'redux';
import {loginReducer} from './loginReducer'

const rootReducer = combineReducers({
    loginReducer,
  });

export default store = createStore(rootReducer)

Upvotes: 0

Views: 86

Answers (2)

Anuradha Kumari
Anuradha Kumari

Reputation: 703

The state which comes into mapStateToProps contains all the combined reducers, so we need to access the reducer name first from the state (like state.loginReducer.user), before trying to access the data of that reducer. PFB code which should work:

function mapStateToProps(state) {
    return {
        user: state.loginReducer.user,
        errorMessage: state.loginReducer.errorMessage
    }
}

Upvotes: 2

Kishan Bharda
Kishan Bharda

Reputation: 5690

Change here :

function mapStateToProps(state) {
    return {
        user: state.user,
        errorMessage: state.errorMessage
    }
}

TO

function mapStateToProps(state) {
    return {
        login: state.loginReducer
    }
}

And then this.props.user to this.props.login.user and this.props.errorMessage to this.props.login.errorMessage in all the occurrence.

Upvotes: 1

Related Questions