user10926450
user10926450

Reputation:

React Redux not getting state in mapStateToProps

I am trying to make user login in my application through react redux but it gives error as

TypeError: undefined is not an object (evaluating 'state.user_name')

app.js

import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import AppDrawer from './drawerNavigator.js';
import  MainNavigator from './screens/stackNavigator'
import { createStore } from 'redux'
import { Provider } from 'react-redux'



  initialState = {
    first_name:"",
    last_name: "",
    user_name: "",
    password: "",  
  }

  const reducer = (state = initialState, action) =>{  
  switch (action.type) {
    case 'SIGN_UP':
    return
       {first_name: state.first_name = action.payload.first_name}        
       {last_name: state.last_name = action.payload.last_name}
       {user_name: state.user_name = action.payload.user_name}         
       {password: state.password = action.payload.password}
      console.log("signUp");
    case 'LOG_IN':
    
    return
     JSON.stringify(action.payload);
  }
  return state
}

const store = createStore(reducer);


export default class App extends React.Component {

constructor(props){
  super(props);  
}

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

      </>
    );
  }
}

Login.js

import React from 'react';
import { StyleSheet, Text, View, Button, TextInput, Image, TouchableHighlight } from 'react-native';
import { connect } from 'react-redux';
import axios from 'axios';
import { NavigationActions } from 'react-navigation';
import { Actions } from 'react-native-router-flux';


class LogIn extends React.Component {

  
  state = {
    user: "",
    pwd: "",
  } 

  render(){
    const navigation = this.props.navigation;
    return(
      <View style={styles.container}>       
                 
      <View  style={styles.inputContainer}>
      <TextInput style={styles.inputs}
              placeholder="User Name"
              underlineColorAndroid='transparent'
              onChangeText={(text)=>this.setState({user: text})}/>
      </View>          
      <View style={styles.inputContainer}>
      <TextInput style={styles.inputs}
              placeholder="Password"
              secureTextEntry={true}
              underlineColorAndroid='transparent'
              onChangeText={(text)=>this.setState({pwd: text})}/>
      </View>        
      <View style={styles.btn}>
      <TouchableHighlight style={[styles.buttonContainer, styles.loginButton]}  onPress = {()=>this.props.logIn(this.state)}>
         <Text style={styles.loginText}>Login</Text>
      </TouchableHighlight> 

       <TouchableHighlight style={styles.buttonContainer}>
            <Text>Forgot your password?</Text>
        </TouchableHighlight>
                
      <TouchableHighlight style={[styles.buttonContainer, styles.loginButton]} onPress = {()=>navigation.navigate('SignUp')}>  
      <Text>Register here</Text>
        </TouchableHighlight>      
      </View>             
      </View>      
      );
   }
}

const mapStateToProps = (state) =>{
  return {   
    user_name: state.user_name,
    password: state.password
  }
}

const mapDispatchToProps = (dispatch,ownProps) =>{
  return{
    logIn: (text) => {
      if(text.user == ""){
        alert("Enter user name");       
      }
      else if(text.pwd == ""){
        alert("Enter Password");       
      }      
      else {
        var body = {email: text.user,password: text.pwd}
        console.log("body",body);
        axios.post('http://user/login',body)
        .then(res=>{
          console.log("res",res);
             dispatch({ type: 'LOG_IN',payload: res});
             ownProps.navigation.navigate('AppDrawer');
        },err=>{         
             alert(err);         
        }) 
      }      
    }
  }
}

export default connect(mapStateToProps,mapDispatchToProps)(LogIn)

signUp.js

import React from 'react';
import { StyleSheet, Text, View, Button, TextInput, Picker, TouchableOpacity, Image, ScrollView, TouchableHighlight } from 'react-native';
import { AppRegistry } from "react-native";
import { connect } from 'react-redux';
import axios from 'axios';

class SignUp extends React.Component {

 
  state = {
    first_name:"",
    last_name: "",
    user_name: "",
    password: "",
  } 

  render() {

    return (
      <View style={styles.container}>

      <View style={styles.inputContainer}>    
      <TextInput style={styles.inputs}
      placeholder="First Name"
      underlineColorAndroid='transparent'
      onChangeText={(text)=>this.setState({first_name: text})}/>
      </View>

      <View style={styles.inputContainer}>    
      <TextInput style={styles.inputs}
      placeholder="Last Name"
      keyboardType="email-address"
      underlineColorAndroid='transparent' onChangeText={(text)=>this.setState({last_name: text})}/>
      </View>

      <View style={styles.inputContainer}>    
      <TextInput style={styles.inputs}
      placeholder="User Name"              
      underlineColorAndroid='transparent'
      onChangeText={(text)=>this.setState({user_name: text})}/>
      </View>  

      <View style={styles.inputContainer}>    
      <TextInput style={styles.inputs}
      placeholder="Password"              
      underlineColorAndroid='transparent'
      secureTextEntry={true} 
      onChangeText={(text)=>this.setState({password: text})}/>
      </View>

      
      <View style={styles.btn}>
      <TouchableHighlight style={[styles.buttonContainer, styles.loginButton]} onPress={()=>this.props.signUp(this.state)}>
      <Text style={styles.loginText}>Register</Text>
      </TouchableHighlight>                 
      </View>  

      </View>
      );
  }
}


function mapStateToProps (state){
  return {
    first_name: state.first_name,    
    last_name: state.last_name,
    user_name: state.user_name,
    password: state.password,
  }
}



function mapDispatchToProps(dispatch,ownProps){
  return{
    signUp: (text) => {
      if (text.first_name=="") {
        alert("Enter First Name");
      } else if(text.last_name == ""){
        alert("Enter Last Name");       
      }
      else if(text.password == ""){
        alert("Enter Password");       
      }
      else if(text.user_name == ""){
        alert("Enter User_name");       
      }
      else {
        var body = {first_name: text.first_name,last_name: text.last_name,user_name: text.user_name,password: text.password}
        console.log("body",body);
        axios.post('http://user/signup',body)
        .then(res=>{
          dispatch({ type: 'SIGN_UP', payload: body})
          console.log({msg: 'added'});
          ownProps.navigation.navigate('Login')
          },err=>{
          alert(err);
        }) 
      }      
    }
  }
}

export default connect(mapStateToProps,mapDispatchToProps)(SignUp)

the error is located at Login.js in mapStateToProps() method my state in App.js is having user_name but it is not getting rendered in Login.js

Upvotes: 0

Views: 773

Answers (2)

mabhijith95a10
mabhijith95a10

Reputation: 436

Your reducer should look this

const reducer = (state = initialState, action) =>{  
  switch (action.type) {
    case 'SIGN_UP':
      return { ...action.payload };
    case 'LOG_IN':
      return JSON.stringify(action.payload);
    default:
      return state;
  }
}

and use semicolon end of statement missing it will create problems in some cases.

Upvotes: 0

lankovova
lankovova

Reputation: 1426

You got specific error here. JS will evaluate code below

case 'SIGN_UP':
return
  {first_name: state.first_name = action.payload.first_name}        
  ...

as

case 'SIGN_UP':
return undefined;
  {first_name: state.first_name = action.payload.first_name}
  ...

Here is the live example

const testReturn = () => {
  return
    { a: 2 }
}

console.log(testReturn())

While properly placed symbol { works just fine

const testReturn = () => {
  return { 
    a: 2 
  }
}

console.log(testReturn())

The same problem you have in your LOG_IN case

return
   JSON.stringify(action.payload)

Upvotes: 1

Related Questions