#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 /…