在我的化简器中,它返回我从api获取的对象数组。我在列表上做了一个console.log,我可以看到该数组,但是当我访问我的react类中的reducer时,它显示为一个空数组,为什么会这样呢? 在我的react文件的render()函数内部,由于某些奇怪的原因,它确实可以打印,但是我有一个函数试图使用化简器中的数据来渲染单独的div,并且数组显示为空。
getList() {
let arr = [];
if(this.props.popular){
arr = this.props.popular.map(item => {
return (
<div key={item.id} className="movie">
<img
src={`https://image.tmdb.org/t/p/w300${item.poster_path}`}
//onClick={() => this.displayModal(item)}
/>
</div>)
})
}
// console.log(arr)
// this.props.updateCurrentShowList(arr);
return arr;
}
我从下面使用的mapstatetoprops函数中使用this.props.popular。
import { FETCH_POPULAR, RESET_POPULAR } from "../Actions/types";
let initialList = [];
export default function(state = initialList, action){
switch(action.type){
case FETCH_POPULAR:
//return action.payload || false;
initialList = initialList.concat(...action.payload);
//console.log(initialList);
return initialList;
case RESET_POPULAR:
initialList = action.payload;
return initialList;
default:
return state;
}
}
在此打印出initialList并工作,然后我将其返回。
这是我的mapStateToProps函数,该函数存在于我要访问该数组的其他文件中。我在我的reducers文件中使用了Combinereducers。
function mapStateToProps(state) {
return {
popular: state.popular
};
}
为什么我在render()中执行this.props.popular可以正确打印,但是无论何时我在其他地方使用它,都不会打印?
动作功能
export const fetchPopular = (searchTypeFormat, page) => async (dispatch) => {
let url = `https://api.themoviedb.org/3/discover/${searchTypeFormat}?api_key=${APIKEY}&language=en-US&sort_by=popularity.desc&include_adult=false&include_video=false&page=${page}`;
//console.log(url);
const res = await axios.get(url);
//console.log(res.data.results)
dispatch({type: FETCH_POPULAR, payload: res.data.results});
};
我的商店创建
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import reducers from './Reducers/index';
import reduxThunk from 'redux-thunk';
const store = createStore(reducers, {}, applyMiddleware(reduxThunk));
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root'));
我这样组合减速器
import { combineReducers } from 'redux';
import authReducer from './authReducer';
import popularReducer from './popularReducer';
import genreListReducer from './genreListReducer';
import searchByGenreReducer from './searchByGenreReducer';
import { reducer as formReducer } from 'redux-form';
import modalReducer from './modalReducer';
import detailsReducer from './moreDetailReducer';
import userDisplayList from './userDisplayList';
export default combineReducers({
auth: authReducer,
form: formReducer,
popular: popularReducer,
genreList: genreListReducer,
searchByGenre: searchByGenreReducer,
modalData: modalReducer,
details: detailsReducer,
displayList: userDisplayList
})
整个组成部分
import React, { Component } from 'react';
import { withRouter } from "react-router-dom";
import { connect } from 'react-redux';
import * as actions from '../Actions';
class SearchPopular extends Component {
constructor(props) {
super(props);
this.state = {
list: [],
page: 1
}
this.getList = this.getList.bind(this);
}
componentWillMount() {
//console.log(this.props.match.params.format)
this.props.fetchPopular(this.props.match.params.format, this.state.page);
console.log(this.props.popular)
console.log(this.getList());
}
getList() {
let arr = [];
if(this.props.popular){
arr = this.props.popular.map(item => {
return (
<div key={item.id} className="movie">
<img
src={`https://image.tmdb.org/t/p/w300${item.poster_path}`}
//onClick={() => this.displayModal(item)}
/>
</div>)
})
}
//console.log(arr)
// this.props.updateCurrentShowList(arr);
return arr;
}
render() {
console.log(this.props.popular);
return (
<div>
</div>
);
}
}
function mapStateToProps(state) {
return {
popular: state.popular,
updatedList: state.displayList
};
}
export default withRouter(connect(mapStateToProps, actions)(SearchPopular));
答案 0 :(得分:4)
您正在以错误的方式声明更新。您要做的是,它将始终始终首先处理空数组,然后将其追加到其中。
case 'FETCH_POPULAR':
return [...state, ...action.payload];
在减速器中尝试。
****主要问题 您正在尝试获取store.popular,但您在商店中没有受欢迎
const composeEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const configureStore = () => {
const store = createStore(
combineReducers({
popular: Your reducer here
}),
composeEnhancer(applyMiddleware(thunk))
);
return store;
}
****新更新
我认为这是函数的问题,对此失去了参考。
这就是为什么我们在构造函数中使用this.getList.bind(this)
的原因
因此,当我们调用this.getList
时,该函数将获取对此的引用并可以使用它。因此,当您直接从任何其他函数调用它时,请使用this.getList.bind(this)
componentWillMount() {
//console.log(this.props.match.params.format)
this.props.fetchPopular(this.props.match.params.format, this.state.page);
console.log(this.props.popular)
console.log(this.getList.bind(this));
}
答案 1 :(得分:2)
不要在Redux reducer中变异变量!您会得到很多奇怪的效果和比赛条件。您要始终从减速器返回新的对象,除非在默认情况下没有动作匹配,然后返回当前的state
。
因此,首先,不要用let
定义初始状态,然后在化简器中对其进行突变,这是完全错误的。
第二,如果要基于先前的状态返回新状态(例如在FETCH_POPULAR动作中),请使用state
参数(这就是它的作用)。
像这样重写
export default function(state = [], action){
switch(action.type){
case FETCH_POPULAR:
return [...state, ...action.payload];
case RESET_POPULAR:
return [];
default:
return state;
}
}