Komail Fayazbakhsh
Komail Fayazbakhsh

Reputation: 384

Can I use more than one action in a component in redux

I have two actions: userIdContainer, and projectContainer.

In componentDidmount, I use these actions to get my projects data and user id

In project.js:

import React , {Component} from "react";
import ProjectCard from "../Partials/Project/ProjectCard";
import AddNewProject from "../Partials/Project/AddNewProject";
import { connect } from "react-redux";
import { userIdContainer } from "../../actions";
import { projectContainer } from "../../actions";
import $ from "jquery";
import { project } from "../../reducers/project";

class Projects extends Component{
  state = {
    projects : [],
  }

  componentDidMount = () =>{
    let token = localStorage.getItem('access_token');
    let config = {
      headers: {'Authorization': "bearer " + token}
    };
    axios.get( 
      '/api/projects',
      config
    ).then(response =>{
      let {projects , userId } = response.data;
      this.props.dispatch(userIdContainer(userId));
      this.props.dispatch(projectContainer(projects));
      this.setState({
        projects : projects
      })
    }).catch(error =>{

    });
  }

  render(){
    console.log(this.props);
    let projects = this.props.projects;
    let aProjects = [];
    if (projects) {
      aProjects = $.map(projects , function(value , index){
        return [<ProjectCard key={index} project={value} />];
      });
    }
    return(
      <div className="card-container">
        {aProjects}
        <AddNewProject />
      </div>
    )
  }
}

const mapStateToProps = (state) => {
  return{
    projects : state.project.projects,
    userId : state.auth.userId
  }
}

export default connect(mapStateToProps)(Projects);

in index.js(my actions)

export const userIdContainer = (userId) => {
  return{
    type : 'USER_ID_CONTAINER',
    userId
  }
};
export const projectContainer = (project) => {
  // console.log(project);
  return {
    type : 'PROJECT_CONTAINER',
    project
  }
}

after that component rendered ,userId returns undefined,

If I remove projectContainer action, userIdContainer works properly.

What is a best way to use more than one action in this component?

i used combine reducer

import { combineReducers } from "redux";
import { auth } from "./auth";
import { project } from "./project";

export default combineReducers({
    auth,
    project
})

this is my auth reducer

export const auth = (state =[] , action ) => {
    // console.log(action.type);
    switch (action.type) {
        case 'IS_TOKEN_VALID' :
            // console.log(action);
            return {
                    token : action.token,
                    isUserLoggedIn : true
                }
            case 'USER_ID_CONTAINER' :
                return {
                        userId : action.userId
                    }
        default :
            return 'default';
    }
}

and project reducer...

export const project = (state =[] , action ) => {
    switch (action.type) {
        case 'PROJECT_CONTAINER' :
            return {
                    ...state , 
                    projects : action.project
                }
        default :
            return 'default';
    }
}

Upvotes: 0

Views: 233

Answers (1)

Gennady Dogaev
Gennady Dogaev

Reputation: 5991

As https://redux.js.org/basics/reducers says,

We return the previous state in the default case. It's important to return the previous state for any unknown action.

Reason for that - Redux passes action to all reducers. Meaning, when you do this.props.dispatch(projectContainer(projects));, both reducers are called.

You need to replace

default :
  return 'default';

with

default :
  return state;

in both reducers.

Also, when you do like this, you overwrite state completely:

return {
  token : action.token,
  isUserLoggedIn : true
}

return {
  userId : action.userId
}

You might need to change it to

return {
  ...state,
  token : action.token,
  isUserLoggedIn : true
}

return {
  ...state,
  userId : action.userId
}

Upvotes: 1

Related Questions