2017-02-22 10 views
1

Я только начал экспериментировать с реакцией и сокращением, и я столкнулся с двумя проблемами на пути.реагировать на действия с редукцией и реактивным маршрутизатором два раза

Когда я пытаюсь отобразить асинхронные данные при изменении маршрута, отправленное действие запускается дважды. Во-первых, это неопределенные данные, а не реальные данные.

Вот мой магазин

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; 

редуктор

export const RESOLVED_GET_PROFILE = 'RESOLVED_GET_PROFILE' 

const profileReducer = (state = {}, action) => { 
    switch (action.type) { 
     case 'SET_PROFILE': 
       return {profile: action.profile} 

     default: 
      return state; 
    } 
}; 

export default profileReducer; 

действия

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

export function getProfile() { 
    return dispatch => { 
     dispatch(setLoadingProfileState()); // Show a loading spinner 
     Api.get('profile').then(profile => { 
      dispatch(doneFetchingProfile); 
      dispatch(setProfile(profile)); 
     }).catch(error => { 
      dispatch(showError(error)); 
      throw(error); 
     }); 
    } 
} 

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


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

function doneFetchingProfile() { 
    return { 
     type: types.HIDE_SPINNER, 
     loaded: true 
    } 
} 

function showError() { 
    return { 
     type: types.SHOW_ERROR, 
     loaded: false, 
     error: 'error' 
    } 
} 

и вот мой компонент

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


class Profile extends Component { 

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

    constructor(props) { 
     super(props); 

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

    onUpdate(event) { 
     alert() 
    } 

    componentDidMount() { 
     //here I dispatch the action 
     this.props.actions.getProfile() 
    } 

    componentWillReceiveProps(nextProps) { 

    } 

    render() { 
     console.log(this.props) 
     //this.props.profile on first is undefined and then filled 
     const { profile } = this.props.profile 

     return (
      <div> 

      </div> 
     ); 
    } 
} 

function mapStateToProps(state) { 

    return { 
     profile: state.default.profile, 
    }; 
} 

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

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

что я не так?

console

ответ

0

Вы сказали //this.props.profile on first is undefined and then filled

Это потому, что в первый рендер, state.profileявляетсяundefined, пока ответ на запрос не поступает и setProfile действие отправляется.

Существует также проблема, которую Андрей отметил, что вы звоните dispatch(doneFetchingProfile). Поскольку вы используете redux-thunk, это вызовет вызов doneFetchingProfile(dispatch, getState), но действие HIDE_SPINNER никогда не будет отправлено.


UPDATE: Там нет ничего плохого с кодом. Вы можете увидеть до SHOW_SPINNER вывод console.log(this.props) и нет profile, потому что в состоянии нет profile.

Затем, когда ваш запрос завершен, profile установлен в состояние, затем передается вашему компоненту, а затем вы можете видеть в журнале, что установлено profile. Это не действия, отправленные, это журнал ваших реквизитов.

Впервые не определено, поскольку начальное состояние, заявленное в редукторе, равно {} (здесь также нет profile).

Если вы изменяете

const profileReducer = (state = {}, action) => { 

в

const profileReducer = (state = {profile: 'some initial value'}, action) => { 

вы увидите, что первый console.log(this.props) покажет profile со значением 'some initial value', а затем перейти к удаленным данным.

+0

, поэтому я попробовал отправку (doneFetchingProfile (profile)) и возвратил профиль, но даже, похоже, это то же самое. Как реорганизовать код, который будет запускаться один раз с данными? – fefe

+0

@fefe Я не понимаю. Как вы смотрите, какие действия отправляются? В соответствии с кодом 'SET_PROFILE' следует отправлять только один раз. Но 'state.profile' принимает 2 значения: начинается с' undefined', а затем устанавливается правильные данные после отправки вышеуказанного действия. – Lucas

+0

Я сделал снимок экрана с консоли – fefe

0

Вы диспетчерская 2 действия

dispatch(doneFetchingProfile); 
dispatch(setProfile(profile)); 

Первый из них не имеют никаких данных, и это выглядеть tihs набора действий изложить некоторые данные и обновить компонент.

+0

На самом деле, с redux-thunk, который просто не будет отправлять какие-либо действия относительно «set profile» – Lucas

1

Это то, что здесь происходит

  1. Вашего компонента визуализация и показать неопределенной на консоль, так как нет данных профиля до сих пор.
  2. После подключения компонента подключите компонент ComponentDidmount, который запускает действие для извлечения данных из URL-адреса.

  3. Вы получаете данные из api и обновляете состояние redux, которое также обновляет ваш компонент.

  4. Поэтому вы оказываете функцию вызывается снова, и на этот раз она показывает данные профиля.

Отправлено 2 раза. Код отлично подходит.

Смежные вопросы