Пытается вернуть массив из хранилища Redux, но возвращает пустой массив

#javascript #reactjs #redux

#javascript #reactjs #redux

Вопрос:

Я пытаюсь вернуть извлеченный массив из хранилища Redux, но возвращаю пустой массив. Кстати, выборка работает хорошо. Я не могу найти ошибку

Возможно, ошибка в reducer или у меня просто есть это в { connect}

выборка данных из tmdb здесь, возвращает array

 action.js

export function itemFetchMovies() {
    return function (dispatch) {
        return fetch(url, {method: 'GET'})
            .then(response => response.json())
            .then(data => {
                console.log(data);
                let movies = [];

                let currentCount = 1;
                function makeCounter() {
                    return function() {
                        return currentCount  ;
                    };
                }

                let counter = makeCounter();
                for (let i = 0; i < data.results.length; i  ) {
                    let image_url = "https://image.tmdb.org/t/p/w500"   data.results[i].poster_path;
                    movies.push({
                        key: {i},
                        number: counter(),
                        poster: <img
                            src={image_url}
                            alt="new"
                            style={{width: 50, height: 50}}
                        />,
                        title: data.results[i].original_title,
                        year: data.results[i].release_date
                    })
                }
                console.log(movies);
                dispatch(
                            {
                                type: 'ITEMS_FETCH_DATA_SUCCESS',
                                payload: movies
                            }
                        );
            });
    }
}
  

Redux reducer, просто хочу обменять начальное состояние на извлеченные данные

 reducer.js

const initalState = {
    list: []
};


export function items(state = initalState, action) {
    switch (action.type) {
        case 'ITEMS_FETCH_DATA_SUCCESS':
            return {
                ...state,
                list: action.payload
            };

        default:
            return state ;
    }
}

  

в componentDidMount вызываю мою функцию выборки через состояния, использую { connect} для подключения ПОРП и сохранения

 App.js


class App extends React.Component {
    componentDidMount() {
        this.props.fetchMovie();
        console.log(this.props)
    }

    render() {
        return (
            <div>
            </div>
        );
    }
}


App.propTypes = {
    fetchMovie: PropTypes.func.isRequired,
    list: PropTypes.array.isRequired,
};


const mapStateToProps = (state) => {
    return {
        list: state.list,
    };
};

const mapDispatchToProps = (dispatch) => {
    return {
        fetchMovie: () => dispatch(itemFetchMovies())
    };
};

export default connect(mapStateToProps, mapDispatchToProps)(App)
  
 index.js

const store = createStore(items, applyMiddleware(thunk));
console.log(store.getState());

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

Комментарии:

1. Где этот пустой массив появляется в вашем коде? В App.js ?

Ответ №1:

Позвольте мне прояснить это,

Проблема:

connect сравнивает только незначительное изменение данных, означает изменение глубины на 1 уровень. В вашем случае вы меняете в movies массив, который connect не может получить, и он не выполняет повторный запуск.

Любое изменение глубины объекта или массива, подобное тому, что вы сделали, не вызовет повторной отправки, потому что connect не будет знать, что значения внутри объекта / массива изменены.

Решение:

Вам нужно добавить переменную counter, которая только увеличивает себя в reducer и просто попадает в mapStateToProps как prop, который вам не нужно использовать где-либо еще, просто чтобы сообщить соединению, что вы что-то изменили внутри массива / объекта.

в reducer

возвращает следующим образом

 dispatch(
 {
  type: 'ITEMS_FETCH_DATA_SUCCESS',
  payload: movies,
  counter: state.counter  ,
 }
);
  

в контейнере

 const mapStateToProps = (state) => {
    return {
        list: state.list,
        counter: state.counter,
    };
};
  

надеюсь, это даст вам помощь и решение.

Комментарии:

1. Вы технически правы в части проблемы, но здесь это неприменимо. state.list каждый раз, когда вызывается reducer, это другой объект, поэтому достаточно поверхностного сравнения. Однако ваше решение, помимо смешивания действия и редуктора, неверно. Предполагается, что вы не должны изменять существующее состояние в редукторе, и тогда вам не нужно выполнять какие-либо встречные трюки. Подробнее читайте здесь: redux.js.org/recipes/structuring-reducers /…