Azilhan Azilhan - 29 days ago 11
React JSX Question

React - Redux - Connect data fetched to Component

I am creating a React application and integrating Redux to it in order to manage the state and do network requests.

I followed the Todo tutorial and I am following the async example from the redux website, but I am stucked.

Here is my problem, I want, in my application, to fetch a user from a remote server. So the server send me a json array containing an object (maybe it's better if the server send me directly an object ? )
The json I obtain looks like that (I put only two fields but there are more in real) :

[{first_name: "Rick", "last_name": "Grimes"}]

Anyway I can fetch the data from the server but I can't inject user's data into my application, I hope you can help me but the most important is that I understand why it doesn't work.

Here are my several files :

I have two actions, one for the request and the other for the response:

actions/index.js

export const REQUEST_CONNECTED_USER = 'REQUEST_CONNECTED_USER';
export const RECEIVE_CONNECTED_USER = 'RECEIVE_CONNECTED_USER';
function requestConnectedUser(){
return {
type: REQUEST_CONNECTED_USER
}
}
function receiveConnectedUser(user){
return {
type: RECEIVE_CONNECTED_USER,
user:user,
receivedAt: Date.now()
}
}
export function fetchConnectedUser(){
return function(dispatch) {
dispatch(requestConnectedUser());

return fetch(`http://local.particeep.com:9000/fake-user`)
.then(response =>
response.json()
)
.then(json =>
dispatch(receiveConnectedUser(json))
)

}
}


reducer/index.js

import { REQUEST_CONNECTED_USER, RECEIVE_CONNECTED_USER } from '../actions
function connectedUser(state= {
}, action){
switch (action.type){
case REQUEST_CONNECTED_USER:
return Object.assign({}, state, {
isFetching: true
});
case RECEIVE_CONNECTED_USER:
return Object.assign({}, state, {
user: action.user,
isFetching: false
});
default:
return state;
}
}


And I have finally my container element, that I have called Profile.js

import React from 'react';
import { fetchConnectedUser } from '../actions';
import { connect } from 'react-redux';

class Profile extends React.Component{
constructor(props){
super(props);
}

componentDidMount() {
const { dispatch } = this.props;
dispatch(fetchConnectedUser());
}

render(){
const { user, isFetching} = this.props;

console.log("Props log :", this.props);
return (

<DashboardContent>

{isFetching &&
<div>
Is fetching
</div>
}

{!isFetching &&
<div>
Call component here and pass user data as props
</div>
}
</DashboardContent>
)
}
}

function mapStateToProps(state) {

const {isFetching, user: connectedUser } = connectedUser || { isFetching: true, user: []}

return {
isFetching,
user: state.connectedUser
}
}


export default connect(mapStateToProps)(Profile)


In the code above, I always have the
Is Fetching
paragraph being display, but even when I remove it, I cannot access to user data.
I think I have the beginning of something because when I console.log I can see my actions being dispatched and the data being added to the state, but I think I am missing something in the link communication with this data to the UI Component.
Am I on the good way or do I have a lot of things to refactor ? Any help would be very helpful !

Answer

Seeing as you are immediately fetching the data I allow myself to assume that isFetching may be true at beginning. Add an initial state to your reducer

state = { isFetching: true, user: null }

Then assuming you setup the reducer correctly:

function mapStateToProps(state) {

    const {isFetching, user } = state.connectedUser

    return {
        isFetching,
        user
    }
}

Hope this works, feels clean-ish.

Comments