1
votes

I am trying to map an action to props however however I'm getting an error: TypeError: _this2.props.updateUsername is not a function

How does one successfully map redux actions to props and call the function successfully? I havnt seen this error pop up in any other stackoverflow question/answers is it a simple mistake? Could it be a wrong setup of redux in .index or .app?

I have tried: - importing without using default export - having different formats of mapDispatchToProps (eg without using bindactioncreators) - fixing typos

  • Component:

    import { updateUsername } from "../../actions/user-actions";
    import React, { Component } from "react";
    import { InputText } from "primereact/inputtext";
    import { Button } from "primereact/button";
    import { Password } from "primereact/password";
    import "./UserLogin.css";
    import { connect } from "react-redux";
    import { bindActionCreators } from 'redux'
    
    export class UserLoginPage extends Component {
      constructor(props) {
        super(props);
        this.state = { //used to be using states so ill leave these here for now
          username: "", 
          password: "",
          renderTryAgain: false
        };
    
        this.checkLoginDetails.bind(this.checkLoginDetails);
      }
    
      async checkLoginDetails() {
        ...
      }
    
      render() {
        const usernameBox = (
          <InputText
            ...
            value={this.props.username}
            onChange={e => this.props.updateUsername(e.target.value)}
          />
        );
    
        const passwordBox = (
          <Password
            ...
          />
        );
    
        const loginButton = (
          <Button
            ...
          />
        );
    
        return (
          <header className="User-login">
            <p>Dashboard User Login</p>
            <div className="p-grid">
              <div className="p-col">{usernameBox}</div>
              <div className="p-col">{passwordBox}</div>
              <div className="p-col">{loginButton}</div>
            </div>
          </header>
        );
      }
    }
    
    const mapStateToProps = state => ({
      username: state.username
    });
    
    const mapDispatchToProps = dispatch => bindActionCreators(
      {
        updateUsername,
      },
      dispatch,
    )
    
    export default connect(
      mapStateToProps,
      mapDispatchToProps
    )(UserLoginPage);
    

Reducers:

import { UPDATE_USERNAME} from '../actions/user-actions'

export function passReducer(state = "", {type, payload}) {
  switch (type) {
    case true:
      return payload
    default:
      return state
  }
}

export function usernameReducer(state = '', {type, payload}) {
  switch (type) {
    case UPDATE_USERNAME:
      return payload.username
    default:
      return state
  }
}

export default { passReducer, usernameReducer };
  • Action:

    export const UPDATE_USERNAME = 'username:updateUsername'
    export function updateUsername(newUsername){
        return {
            type: UPDATE_USERNAME,
            payload: {
                username: newUsername
            }
        }
    }
    
    export default {UPDATE_USERNAME, updateUsername}
    

Many Thanks

2
check your mapDispatchToPropsJoseph D.
Your action name is updateUsername not onUpdateUsername check your typo.Arvindh
Fixed typo, but still the same errorizzyp

2 Answers

1
votes

Can you check once after updating your constructor as below?

constructor(props) {
    super(props);
    //...
  }
1
votes

Don't use mapDispatchToProps. Instead just wrap all the actions you want to map inside an object and pass them as the second argument to the connect helper method.

Like this connect(mapStateToProps, { updateUsername })(UserLoginPage)

Hope this helps!