React + Redux: компонент не обновляется

Попробуйте React + Redux, и, возможно, я делаю что-то явно глупое, потому что компонент, который запускает действие для извлечения данных по сети, не обновляется (перерисовывается), когда данные извлекаются.

Вот соответствующие биты моего кода:

Index.js верхнего уровня, служащий точкой входа для приложения:

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { Router, browserHistory } from 'react-router';
import reduxPromise from 'redux-promise';
import createLogger from 'redux-logger';

const logger = createLogger();

import routes from './routes';
import reducers from './reducers';

const createStoreWithMiddleware = applyMiddleware(reduxPromise, logger)(createStore);

ReactDOM.render(
  <Provider store={createStoreWithMiddleware(reducers)}>
    <Router history={browserHistory} routes={routes} />
  </Provider>
  , document.querySelector('.container'));

Контейнер верхнего уровня

import React, {Component} from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as Actions from '../actions';
import Header from '../components/header';
import Showcase from '../components/showcase';

function mapStateToProps(state) {
  return {
    resources: state.resources
  }
}

function mapDispatchToProps(dispatch) {
  return {
    fetchResources: () => {
      dispatch(Actions.fetchResources());
    }
  }
}


class App extends Component {

  render() {
    console.log('props in App', this.props);
    return (
      <div>
        <Header/>
        <Showcase
          fetchResources={this.props.fetchResources}
          resources={this.props.resources}
        />
      </div>
    );
  }
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App)

Компонент, который запускает действие для отправки запроса данных, когда он собирается смонтировать, и должен показывать извлеченные данные:

import React, {Component} from 'react';
import {connect} from 'react-redux';

class Showcase extends Component {
  constructor(props) {
    super(props);
  }

  componentWillMount() {
    this.props.fetchResources();
  }

  render() {
    console.log('resources', this.props);
    return (
      <div>
        This is showcase
      </div>
    );
  }
}

export default connect(state => ({resources: state.resources}))(Showcase)

Создатель действий:

import * as types from '../constants/ActionTypes';
import axios from 'axios';

export function fetchResources() {
  return {
    type: types.FETCH_FIRST,
    payload: axios.get('/sampledata/1.json')
  }
}

Редуктор для действия при извлечении:

import * as types from '../constants/ActionTypes';

export default function resourcesReducer (state={}, action) {
  switch (action.type) {
    case types.FETCH_FIRST:
      console.log('about to return', Object.assign (state, {resources: action.payload.data }))
      return Object.assign (state, {resources: action.payload.data });
    default:
      return state
  }
};

и, наконец, корневой редуктор:

import { combineReducers } from 'redux';
import navigationReducer from './navigation-reducer';
import resourcesReducer from './resources-reducer';

const rootReducer = combineReducers({
  navigationReducer,
  resourcesReducer
});

export default rootReducer;

Итак, вот что я наблюдаю. Действие для запроса данных успешно инициировано, запрос отправляется, редуктор получает его, когда обещание разрешается, и обновляет состояние с выбранными данными. На данный момент, я бы ожидал на высшем уровнеApp компонент иShowcase компонент для обнаружения того, что магазин обновился, и для повторного рендеринга, но я не вижу его в консоли.

Кроме того, я смущенredux-loggerКонсольный вывод:

В частности, я удивлен, увидев, чтоstate содержит редукторы от rootReducer - я не знаю, правильно ли это (пример наRedux logger Github page показывает состояние без редукторов). Также кажется удивительным, чтоprev state как сообщаетсяredux-logger содержит то же самоеresourcesReducer объект какnext stateхотя интуитивно я бы ожидалprev state быть более или менее пустым.

Не могли бы вы указать, что я делаю неправильно и как заставить компоненты React реагировать наstate изменения?

==================================================

ОБНОВЛЕНО:

1) поменялmapStateToProps функция вApp компонент, так что он правильно отображается в состояния редуктора:

function mapStateToProps(state) {
  return {
    resources: state.resourcesReducer
  }
}

2) Все еще прохождениеresources вплоть до `Showcase компонента:

  render() {
    console.log('props in App', this.props);
    return (
      <div>
        <Header navigateActions={this.props.navigateActions}/>
        React simple starter
        <Showcase
          fetchResources={this.props.fetchResources}
          resources={this.props.resources}
        />
      </div>
    );

3) Попытка отобразитьresources на экране, чтобы увидеть, что на самом деле внутри этого объекта:

  render() {
    console.log('resources', this.props);
    return (
      <div>
        This is showcase {JSON.stringify(this.props.resources)}
      </div>
    );
  }

Смотрите это на экране:This is showcase {}, Компонент не рендерится.

Вот снимок экрана консоли, показывающий, что реквизиты приложения обновлены значениями изnext state, Тем не менее, это не привело к повторной визуализации компонента:

ОБНОВЛЕНО СНОВА: И мой javascript-фу тоже был беден. Я не совсем понял, что, возвращаясьObject.assign (state, {resources: action.payload.data }); Я фактически мутировал в этом состоянии, и что простая инверсия аргументов позволила бы мне достичь того, что я хотел. Благодаряэто обсуждение на ТАК для просветления.

Ответы на вопрос(1)

Ваш ответ на вопрос