【问题标题】:How can mapStateToProps receive the updated state in react-redux implementationmapStateToProps 如何在 react-redux 实现中接收更新的状态
【发布时间】:2016-12-19 00:25:15
【问题描述】:

我正在学习 react 和 redux 的实现,遇到了一个我找不到修复的错误。 函数mapStateToProps 获取初始(和空)状态。 我正在对状态对象使用无缝不可变,并且我知道我的减速器实际上正在被调用并更新状态。 我已经尝试了所有与组件道具相关的方法(componentWillReceivePropscomponentWillMountcomponentDidMount 等),并且 mapStateToProps 永远不会收到 updated 状态;总是初始空状态。它在this.props.dispatch 可以在这些方法中被调用之前运行。

我一定是错过了什么……

相关文件:

1. app/index.js

import React, { Component } from 'react';
import logo from './logo.svg';
import './index.css';
import PlaylistList from '../../components/PlaylistList';
import { fetchPlaylists } from '../../store/playlists/actions';
import { getPlaylists } from '../../store/playlists/reducer';
import { connect } from 'react-redux';

class App extends Component {
  componentWillReceiveProps() {
    this.props.dispatch(fetchPlaylists();
  }
  render() {
    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h2>Welcome to My Music Store</h2>
        </div>
        <PlaylistList playlists={this.props.playlists}></PlaylistList>
      </div>
    );
  }
}

function mapStateToProps(state) {
  console.dir(state); // prints the initial state (before reducer run)
  return {playlists: getPlaylists(state)}
}

export default connect(mapStateToProps)(App);

2。 actions.js:

import * as api from '../../services/api';
import * as types from './actionTypes';
import _keyBy from 'lodash/keyBy';

export function fetchPlaylists() {
  return async (dispatch, getState) => {
    try{
      const playlists = await api.fetchPlaylists();
      const playlistsById = _keyBy(playlists, (playlist) => playlist.id);
      dispatch( {  type: types.PLAYLISTS_FETCHED, playlistsById} );
    } catch (error) {
      console.error(error);
    }
  }
}

3. reducer.js:

import * as types from './actionTypes';
import _mapKeys from 'lodash/mapKeys';
import _mapValues from 'lodash/mapValues';
import Immutable from 'seamless-immutable';

const initialState = Immutable({
    playlistsById: {},
    currentPlaylist: undefined
  }
);

export default function reduce(state = initialState, action = {}){
  switch (action.type) {
    case types.PLAYLISTS_FETCHED:
      return state.merge({
        playlistsById: action.playlistsById
      })
    default: return state

  }
}

export function getPlaylists(state) {
  let playlistsById = state.playlistsById;
  let playlistIds = _mapKeys(state.playlistsById);
  console.dir({playlistsById, playlistIds}); // prints empty objects
}

4. reducers.js:

import playlistsReducer from './playlists/reducer';

export { playlistsReducer };

5. actionTypes.js

export const PLAYLISTS_FETCHED = 'playlists.PLAYLISTS_FETCHED';
export const PLAYLIST_ADDED = 'playlists.PLAYLIST_ADDED';
export const PLAYLIST_REMOVED = 'playlists.PLAYLIST_REMOVED';
export const PLAYLIST_UPDATED = 'playlists.PLAYLIST_UPDATED';
export const FILTER_BY_SEARCH = 'playlists.FILTER_BY_SEARCH';

6. src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, applyMiddleware, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import thunk from 'redux-thunk';
import App from './containers/App';
import './index.css';
import * as reducers from './store/reducers';

const store = createStore(combineReducers(reducers), applyMiddleware(thunk));

ReactDOM.render(
  <Provider store={store}>
      <App />
  </Provider>,
  document.getElementById('root')
);

【问题讨论】:

    标签: javascript reactjs redux react-redux immutable.js


    【解决方案1】:

    您的实现的问题在于,在 mapStateToProps 中,您希望 state 参数引用您的 playlistsReducer 的状态,而实际上它引用的是整个状态对象,其中所有减速器由 combineReducers 组合功能。

    该州中playlistsReducer 的正确路径是 - state.playlistsReducer。因此,您的 mapStateToProps 必须如下所示:

    function mapStateToProps(state) {
      console.dir(state.playlistsReducer); // prints the initial state (before reducer run)
      return {playlists: getPlaylists(state.playlistsReducer)}
    }
    

    通过使用这个mapStateToPropsgetPlaylists 将接收到带有所需数据的正确对象,以将所需的道具传递给组件。

    另一个主要问题是getPlaylists 方法不返回任何内容。

    【讨论】:

    • 好吧,我把它改成了state.playlistsReducer,但没有用。仍然不包含任何数据...
    • 如果你说状态是在动作被调度时更新并且mapStateToProps没有在它之后被调用,那看起来很奇怪。你能把这段代码放在一些开发者游乐场,比如codepen.io,这样我就可以玩了吗?
    • 所以,我测试了您的代码并注意到以下问题: 1) 您应该检查组件的渲染方法中的this.props.playlists 是否不是undefined,否则您将收到异常. 2) 您需要使用componentDidMount 而不是componentWillReceiveProps,因为在初始加载期间不会调用前者。 3) getPlaylists 函数不返回任何内容。修复这些问题后,您会注意到组件的 render 方法中的 map 函数不适合您在 prop 中接收的数据类型。
    猜你喜欢
    • 2017-09-21
    • 2021-02-15
    • 2018-07-26
    • 2019-11-10
    • 1970-01-01
    • 2021-07-27
    • 2020-08-07
    • 2021-10-29
    • 1970-01-01
    相关资源
    最近更新 更多