I am using react, redux and redux-saga for my project. While fetching a list of users using Redux-saga, I can see that my redux store is getting updated (I can see it from the redux dev tool), But in the component , props are not changing.
I am using a button to get the list of users. And the users are showing up in that component only.
App.js
import React, { Component } from 'react';
import { connect } from "react-redux";
import './App.css';
import { fetchUsers } from "./actions";
import { Row, Col, ListGroup, ListGroupItem } from "reactstrap";
class App extends Component {
// eslint-disable-next-line no-useless-constructor
constructor(props){
super(props);
}
render() {
console.log("in render func");
console.log(this.props);
return (
<div className="App">
<h2>Redux Saga App</h2>
<Row>
<Col sm={6}>
{this.props.userList?this.props.userList.map((user)=>(
user.first_name + user.last_name
)) : ''}
</Col>
</Row>
<button onClick={this.props.getUserList}>Click to get the users</button>
</div>
);
}
}
const mapStateToProps = (state)=>{
console.log("in map statetpprop");
//console.log(state.userList);
return {userList:state.userList}
}
const mapDispatchToProps = (dispatch)=>{
return {getUserList :() => {dispatch(fetchUsers())}}
}
App = connect(mapStateToProps,mapDispatchToProps)(App);
export default App;
action.js
export function fetchUsers(){
return {
type:'FETCH_USERS',
}
}
reducer.js
const initialState = {
userList:[]
}
export function userReducer(state=initialState,action){
switch(action.type){
case 'ADD_USER':
return Object.assign(state,{
user:action.data
})
case 'SET_USERS':
return Object.assign(state, {userList : action.data});
default:
return state;
}
}
saga.js
import {call, put , takeEvery , takeLatest } from 'redux-saga/effects';
import axios from 'axios';
import { setUsers } from "./actions";
export function fetchUsersFunc(userId){
return axios.get('https://reqres.in/api/users');
}
function* fetchUsers(action){
const users = yield call(fetchUsersFunc);
console.log("in fetch users");
if(users.data.data){
const userList = users.data.data;
console.log(userList);
console.log(userList[0].first_name)
yield put(setUsers(userList));
}
}
export function* rootSaga(){
yield [
takeLatest('FETCH_USERS',fetchUsers)
];
}
Thanks for the help!
If you use Object.assign
and you want to make a new copy of the state, you need to make the target object to a new empty object instead of what you are currently doing (it mutates the state
object, which makes the react unable to re-render). (You can see See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign for more information on Object.assign
) For example:
// copy previous state and new updates to a new empty object
return Object.assign({}, state, {userList : action.data});
I would recommend using the spread operator instead of Object.assign
though:
return {...state, userList : action.data}