Reputation: 2800
I connected Home component props with action method and dispatch the reducer successfuly. All seems to work fine, I can see Api data coming to reducer in console.
Problem is, react doesn't re-render ProfileGroupsWidget. this.props.user is always {} in this child component, I was expecting it to be {name: "John Doe"}
Here is userReducer, "GET_AUTH_USER_SUCCESS" comes from getAuthenticatedUser:
const initialState = {};
const userReducer = (state = initialState, action) => {
switch (action.type) {
case 'GET_AUTH_USER_SUCCESS':
console.log('Output:', action.user); // {name: "John Doe"}
state = action.user
return state;
default:
return state
}
}
export {userReducer}
Home is my Home component:
import React, { Component } from 'react';
import ProfileGroupsWidget from './Widgets/ProfileGroupsWidget.js'
import {connect} from 'react-redux'
import {userActions} from "../_actions/userActions";
class Home extends Component{
constructor(props) {
super(props);
this.state = {
user: this.props.user
}
this.props.getAuthenticatedUser();
}
render() {
return (
<ProfileGroupsWidget user={this.state.user}></ProfileGroupsWidget>
)
}
}
const mapStateToProps = state => {
return state
}
function mapDispatchToProps(dispatch){
return {
getAuthenticatedUser : () => {dispatch(userActions.getAuthenticatedUser())}
}
}
// Connect Home component props with store data:
export default connect(mapStateToProps, mapDispatchToProps)(Home);
Upvotes: 1
Views: 53
Reputation: 755
Why are you passing props.user to your state? That should be unnecessary based on your current code. With that, it would be better to assign this.props.user
directly to ProfileGroupsWidget. That is if your redux is working and connected properly to your component.
Another thing here (Calling action from constructor vs a life cycle method), it's better to call network requests or actions inside componentDidMount
rather than in your constructor:
componentDidMount() {
this.props.getAuthenticatedUser();
}
If you have everything correct you should see multiple console.logs of this.props.user
if you log it inside render():
render() {
console.log(this.props.user);
/*
should be called at least twice,
the last one containing the data {name: "John Doe"}
*/
return (
<ProfileGroupsWidget user={this.props.user}></ProfileGroupsWidget>
)
...
Upvotes: 2
Reputation: 4182
In your code, this.props.user
will always be undefined because you are not setting the value for it in the reducer. We have to set the value in the following way:
Edited Code:
const initialState = {
user: {}
};
const userReducer = (state = initialState, action) => {
switch (action.type) {
case 'GET_AUTH_USER_SUCCESS':
return { ...state, user: action.user };
default:
return state;
}
}
export { userReducer }
Edited Code:
In home component: (in mapStateToProps, I have maintained userReducer
as identifier, please change it to whatever reducer name you have used in the rootReducer).
We can also remove the constructor code entirely if you like, and move the action dispatch to componentWillMount()
.
import React, { Component } from 'react';
import ProfileGroupsWidget from './Widgets/ProfileGroupsWidget.js'
import { connect } from 'react-redux'
import { userActions } from "../_actions/userActions";
class Home extends Component{
constructor(props) {
super(props);
this.state = {
user: props.user
}
props.getAuthenticatedUser();
}
render() {
return (
<ProfileGroupsWidget user={this.props.user}></ProfileGroupsWidget>
)
}
}
const mapStateToProps = state => ({
user: state.userReducer.user
});
const mapDispatchToProps = (dispatch) => ({
getAuthenticatedUser: () => dispatch(userActions.getAuthenticatedUser())
});
// Connect Home component props with store data:
export default connect(mapStateToProps, mapDispatchToProps)(Home);
Upvotes: 2