3

I try to deal with ajax data in my learning react,redux project and I have no idea how to dispatch an action and set the state inside a component

here is my component

import React, {PropTypes, Component} from 'react';
import Upload from './Upload';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import * as profileActions from '../../../actions/profileActions';


class Profile extends Component {

    static propTypes = {
        //getProfile: PropTypes.func.isRequired,
        //profile: PropTypes.object.isRequired,
    };

    constructor(props) {
        super(props);

        this.state = {
            profile:{
                username: '',
                password: ''
            }
        }
        this.onUpdate = this.onUpdate.bind(this)
    }

    onUpdate(event) {
        alert()
    }

    componentWillMount() {
    }

    componentDidMount() {
    }


    render() {

        const {profile} = this.props;
        return (
            <div>

            </div>
        );
    }
}

function mapStateToProps(state) {
    console.log(state)
    return {
        profile: state.default.profile,
    };
}

function mapDispatchToProps(dispatch, ownProps) {
    return {
        actions: bindActionCreators(profileActions, dispatch)
    };
}

export default connect(mapStateToProps, mapDispatchToProps)(Profile);

I create the store as it follows

import { createStore, combineReducers, applyMiddleware } from 'redux'
import createLogger from 'redux-logger'
import thunk from 'redux-thunk'
import { routerReducer, routerMiddleware, push } from 'react-router-redux'
import reducers from '../reducers'
import { browserHistory } from 'react-router';

const middleware = [ thunk ];
if (process.env.NODE_ENV !== 'production') {
    middleware.push(createLogger());
}

middleware.push(routerMiddleware(browserHistory));

// Add the reducer to your store on the `routing` key
const store = createStore(
    combineReducers({
        reducers,
        routing: routerReducer
    }),
    applyMiddleware(...middleware),

)

export default store;

reducer

export const RESOLVED_GET_PROFILE = 'RESOLVED_GET_PROFILE'

const profileReducer = (state = {}, action) => {
    switch (action.type) {
        case 'RESOLVED_GET_PROFILE':
            return action.data;
        default:
            return state;
    }
};

export default profileReducer;

actions

import * as types from './actionTypes';
import Api from '../middleware/Api';

export function getProfile() {
    return dispatch => {
        dispatch(setLoadingProfileState()); // Show a loading spinner
        Api.getAll('profile').then(profile => {
            dispatch(doneFetchingProfile(profile));
        }).catch(error => {
            throw(error);
        });
        /*Api.fetch(`profile`, (response) => {
            console.log(response)
            dispatch(doneFetchingBook()); // Hide loading spinner
            if(response.status == 200){
                dispatch(setProfile(response.json)); // Use a normal function to set the received state
            }else {
                dispatch(error)
            }
        }) */
    }
}

function setProfile(data) {
    return {type: types.SET_PROFILE, data: data}
    //return { type: types.SET_PROFILE, data: data };
}


function setLoadingProfileState() {
    return {type: types.SHOW_SPINNER}
}

function doneFetchingProfile(data) {
    console.log(data)
    return {
        type: types.HIDE_SPINNER,
        profile: data
    }
}

function error() {
    return {type: types.SHOW_ERROR}
}

but I have no idea how would I dispatch action and update the state after getProfile action

fefe
  • 8,755
  • 27
  • 104
  • 180

1 Answers1

0

You need to only dispatch your event RESOLVED_GET_PROFILE right after dispatching doneFetchingProfile, or simply listen RESOLVED_GET_PROFILE and hide spinner on reducing it.

 Api.getAll('profile').then(profile => {
    dispatch(doneFetchingProfile(profile));
    dispatch(resoloveGetProfile(profile));
 })

Actually you r doing everything right - so I didn't understand what is your question is, so if you meant something else - let me know, I`ll try to describe you.

About dispatch(resoloveGetProfile(profile));

There you dispatch action, which will update your state, simple as you do with some static state, I saw that you already have setProfile action, so you can change that line, to call your existed function.

dispatch(setProfile(profile))

Than you need to reduce your state in this action

case 'SET_PROFILE' : (action, state) => {...state, profile: action.data}

Than your state will change and your components will update. Note that your 'get profile method' better to call from componentDidMount to avoid freezing at rendering because of performing web request.

Dmitriy Kovalenko
  • 3,437
  • 3
  • 19
  • 39