【问题标题】:Redux state props undefined and ComponentDidMount not firingRedux 状态道具未定义且 ComponentDidMount 未触发
【发布时间】:2018-09-20 17:08:27
【问题描述】:

在我的 localhost react-node 应用程序中,当我点击 Movies.js 页面时,该应用程序将对 {localhost}/api/movies 节点端点进行 api 调用(顺便说一句,我正在使用 redux-thunk 中间件)。

然后它将一个 json 返回到 this.props.movies.displayedMovies(入口点是 componentDidMount()),然后将其传递给 render()

从那以后,唯一的变化是我添加了另一个reducer MusicReducer 并使用redux 的combinedReducer(..) 来配置store。

现在,电影页面呈现空白,因为控制台返回 Cannot read property 'displayedMovies' of undefined 并且似乎没有调用 componentDidMount。

不确定是什么问题。下面是代码。任何帮助,将不胜感激。

Movies.js 容器

import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter as Router, Route } from 'react-router-dom'

import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import * as moviesActions from '../actions/MoviesActions'

import NavBar from '../components/NavBar'
import ResultsBar from '../components/ResultsBar'
import Grid from '../components/Grid'
import * as utils from '../utils/utils.js'
import style from '../style/App.css'

class Movies extends Component {

  handleSearch(e) {
    this.props.moviesActions.filterMovies(e.target.value)
  }

  componentDidMount() {
    this.props.moviesActions.fetchMovies()
  }

  render() {
    let { displayedMovies } = this.props.movies

    return (
      <div>
      <NavBar onChange={this.handleSearch.bind(this)} type={0}/>
      <br/>
      <ResultsBar count={displayedMovies.length} type={0}/>
      <Grid
          gridData={JSON.stringify(displayedMovies)}
          gridCell_width={140}
          gridCell_height={200}
          type={0}
      />
      </div>
    );
  }
}

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

function mapDispatchToProps(dispatch) {
  return {
    moviesActions: bindActionCreators(moviesActions, dispatch)
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Movies)

MoviesActions.js 动作

import {
  REQUEST_MOVIES,
  RECEIVE_MOVIES,
  FILTER_MOVIES,
  SORT_MOVIES
} from '../constants/Page'
import * as utils from '../utils/utils.js'

function requestMovies() {
  return {
    type: REQUEST_MOVIES
  }
}

function receiveMovies(json) {
  return {
    type: RECEIVE_MOVIES,
    movies: json
  }
}

export function fetchMovies() {

  return dispatch => {
    dispatch(requestMovies())

    utils.callApi('/api/movies')
      .then(items => {
        var data = [];
        for (var i = 0; i < items.length; i++) {
          data.push({
            tmdb_id: items[i].id, 
            imdb_id: items[i].imdb_id, 
            title: items[i].title, 
            poster_path: 'https://image.tmdb.org/t/p/w500' + items[i].poster_path,
            backdrop_path: 'https://image.tmdb.org/t/p/original' + items[i].backdrop_path, 
            url_path: items[i].url_path, 
            release_date: items[i].release_date, 
            runtime: items[i].runtime, 
            revenue: items[i].revenue,
            overview: items[i].overview,
            tagline: items[i].tagline, 
            link: 'http://www.imdb.com/title/' + items[i].imdb_id
          });
        }
        dispatch(receiveMovies(data))
      })
      .catch(err => console.log(err));
  }

}

export function filterMovies(searchTerm) {
  return {
    type: FILTER_MOVIES,
    searchTerm
  }
}

export function sortMovies(sortOption) {
  return {
    type: SORT_MOVIES,
    sortOption
  }
}

index.js 减速器

import { combineReducers } from 'redux'
import {
  BOOKS,
  COMICS,
  MOVIES,
  MUSIC,
  PODCASTS,
  TV
} from '../constants/Page'
import moviesReducer from './MoviesReducer'
import musicReducer from './MusicReducer'

export default combineReducers({
  moviesReducer,
  musicReducer
})

MoviesReducer.js 减速器

import {
  REQUEST_MOVIES,
  RECEIVE_MOVIES,
  FILTER_MOVIES,
  SORT_MOVIES
} from '../constants/Page'

const initialState = {
  movies: [],
  displayedMovies: []
}

export default function movie(state = initialState, action) {
  switch (action.type) {
    case REQUEST_MOVIES:
      return {
        ...state
      }

    case RECEIVE_MOVIES:
      let movies = action.movies
      return {
        ...state,
        movies,
        displayedMovies: movies
      }

    case FILTER_MOVIES:
      let displayedMovies = state.movies.filter(movie => {
        if (movie.title.toLowerCase().includes(action.searchTerm.toLowerCase())) {
          return true
        }
        return false
      })
      return {
        ...state,
        displayedMovies,
        displayedMovies: displayedMovies
      }

    case SORT_MOVIES:
      let sortDisplayedMovies
      switch(action.sortOption) {
        case 'Alphabetical':
          sortDisplayedMovies = state.displayedMovies.sort((a,b)=> {
            var a1 = a.title.toLowerCase();
            var b1 = b.title.toLowerCase();
            return a1<b1 ?-1:a1> b1? 1 :0;
          })
          break;
        case 'Oldest':
          sortDisplayedMovies = state.displayedMovies.sort((a,b)=> {
            return new Date(a.release_date).getTime() - new Date(b.release_date).getTime();
          })
          break;
        case 'Newest':
          sortDisplayedMovies = state.displayedMovies.sort((a,b)=> {
            return new Date(b.release_date).getTime() - new Date(a.release_date).getTime();
          })
          break;
        default:
          break;
      }
      return {
        ...state,
        sortDisplayedMovies,
        displayedMovies: sortDisplayedMovies
      }

    default:
      return state
  }

}

configureStore.js 存储

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from '../reducers/index'

export default function configureStore() {
  const store = createStore(
    rootReducer, 
    applyMiddleware(thunk)
  );

  return store;
}

【问题讨论】:

    标签: node.js reactjs redux react-redux


    【解决方案1】:

    这是您的mapStateToProps 的问题。

    因为您已将combineReducers 定义如下

    export default combineReducers({
      moviesReducer,
      musicReducer
    })
    

    和下面的一样

    export default combineReducers({
      movieReducer:movieReducer,
      musicReducer:musicReducer
    })
    

    你的电影状态在

    state.movieReducer.movies
    

    这意味着在您的 mapStateToProps 中您必须像这样注入正确的值

    function mapStateToProps(state) {
      return {
        movies: state.movieReducer.movies
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-11
      • 2021-01-26
      • 1970-01-01
      • 2021-04-28
      • 1970-01-01
      • 1970-01-01
      • 2017-11-07
      • 1970-01-01
      相关资源
      最近更新 更多