Redux 状态道具未定义且 ComponentDidMount 未触发
Posted
技术标签:
【中文标题】Redux 状态道具未定义且 ComponentDidMount 未触发【英文标题】:Redux state props undefined and ComponentDidMount not firing 【发布时间】: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;
【问题讨论】:
【参考方案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
【讨论】:
以上是关于Redux 状态道具未定义且 ComponentDidMount 未触发的主要内容,如果未能解决你的问题,请参考以下文章
Redux 状态未在开发工具中更新,但当前状态正在反映在道具中
React Redux TypeError:无法读取未定义的属性“地图”
REACT + REDUX:在 redux 状态更改时 mapStateToProps 更新状态,但视图未按照新状态呈现