简体   繁体   English

为什么我的reducer在react / redux中返回一个空数组?

[英]Why is my reducer returning an empty array in react/redux?

In my reducer, it returns an array of objects that i got from an api. 在我的reducer中,它返回一个从api获得的对象数组。 I do a console.log on the list and I'm able to see the array, but when I get access to the reducer in my react class, it shows up as an empty array, why is that so? 我在列表上做了一个console.log,我能够看到数组,但是当我在反应类中访问reducer时,它显示为一个空数组,为什么会这样呢? Inside the render() function in my react file, it does print for some odd reason, but I have a function where I'm trying to render seperate divs using that data from the reducer and the array shows up empty. 在我的react文件中的render()函数内部,它确实打印了一些奇怪的原因,但我有一个函数,我正在尝试使用reducer中的数据渲染单独的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;
    }

I use this.props.popular from the mapstatetoprops function i have below. 我在下面的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;
    }
}

Here the initialList is printed and works and i then return it. 这里初始列表打印并工作,然后我返回它。

This is my mapStateToProps function that i have in my other file where I want to get access to the array. 这是我的mapStateToProps函数,我在我的其他文件中,我想要访问该数组。 I used combinereducers in one of my reducers file. 我在我的一个reducers文件中使用了combinereducers。

function mapStateToProps(state) {
    return {
        popular: state.popular
    };
}

Why does this.props.popular print correctly when i do it in render(), but whenever i use it anywhere else, it doesnt? 当我在render()中执行此操作时,为什么this.props.popular会正确打印,但每当我在其他任何地方使用它时,它都没有?

action function 动作功能

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});
};

my store creation 我的商店创作

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'));

I combined my reducers this way 我用这种方式组合了我的减速器

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
})

the whole component 整个组成部分

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));

You are doing to state update in a wrong way. 您正在以错误的方式声明更新。 What you have done is it will always take empty array initially and then append into it. 你所做的是它最初将采用空数组,然后附加到其中。

case 'FETCH_POPULAR':
        return [...state, ...action.payload];

Try this in your reducer. 在你的减速机中尝试这个。

****To your main issue You are trying to fetch store.popular but you donot have popular in store ****您的主要问题您正在尝试获取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;
}

**** New update ****新的更新

I think that's the issue of function loosing the reference of this. 我认为这是功能失去参考的问题。 This is why we are using this.getList.bind(this) in the constructor So when we call this.getList the function gets the reference of this and can use it. 这就是为什么我们在构造函数中使用this.getList.bind(this)所以当我们调用this.getList ,函数会获取this的引用并可以使用它。 so when you are calling it directly from any other function then use this.getList.bind(this) 所以当你直接从任何其他函数调用它时,请使用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));
    }

Don't mutate variables in Redux reducers! 不要在Redux redurs中改变变量! You'll get lots of weird effects and race conditions. 你会得到许多奇怪的效果和竞争条件。 You want to always return fresh new objects from a reducer, unless no action matches in the default case, then return the current state . 您希望始终从reducer返回新的新对象,除非在默认情况下没有操作匹配,然后返回当前state

So firstly, don't define your initial state with a let and then mutate it in your reducers, that's completely wrong. 首先,不要用let定义你的初始状态,然后在你的reducer中改变它,这是完全错误的。

Secondly, if you want to return new state based on the previous state, as in your FETCH_POPULAR action, then use the state argument (that's what it's for). 其次,如果你想基于先前的状态返回新的状态,就像你的FETCH_POPULAR动作一样,那么使用state参数(这就是它的用途)。

Rewrite like this, 像这样重写,

export default function(state = [], action){
  switch(action.type){
    case FETCH_POPULAR:
      return [...state, ...action.payload];
    case RESET_POPULAR:
      return [];
    default:
      return state;
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM