#redux #react-redux #redux-saga #use-effect
#redux #react-redux #redux-saga #использование-эффект
Вопрос:
Я пытаюсь получить некоторые данные в компоненте react с помощью useEffect
перехвата. После первоначального рендеринга fetchItems()
получает элементы и обновляет хранилище. Однако он по- items
прежнему остается пустым объектом даже после обновления хранилища.
Возможно, я использую useEffects
неправильно. Как вы используете Redux с useEffects
? Я хочу установить состояние загрузки для компонента, но поскольку компонент отправляет действие только для извлечения элементов (вместо прямого вызова API), он не знает, когда данные извлекаются и хранилище обновляется, чтобы оно могло их извлекать.
Может кто-нибудь, пожалуйста, помочь выяснить, как убедиться, что items
объект обновляется после выборки saga и последующего обновления хранилища?
import React, { useState, useEffect } from "react";
import { connect } from 'react-redux';
import { useParams } from "react-router-dom";
const ItemComponent = ({ item, fetchItem }) => {
const { itemId } = useParams();
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
setIsLoading(true)
fetchItem(itemId)
setIsLoading(false)
}, []);
console.log(item) // gives empty object even after the fetch and store update
}
const mapStateToProps = (state) => {
return {
item: state.item
}
}
const mapDispatchToProps = (dispatch) => {
return {
fetchItem: (itemId) => { dispatch(fetchItemActionCreator(itemId)) }
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ItemComponent);
fetchItemActionCreator
является создателем действия, который создает действие для отправки.- Мой редуктор и saga работают нормально, поскольку я вижу действия и обновления хранилища в консоли.
- Если я передам
items
объект в массив зависимостей foruseEffect
, тогда будет бесконечный цикл, и страница продолжит повторный рендеринг.
Редуктор:
const itemReducer = (state={}, { type, payload }) => {
switch(type) {
case ITEM_GET_SUCCESS:
return {...state, ...payload}
default: return state
}
}
fetchItemActionCreator:
import { createAction } from '@reduxjs/toolkit';
export const fetchItemActionCreator = createAction(ITEM_GET_PENDING);
Заранее большое вам спасибо!
Комментарии:
1. Не могли бы вы поделиться своими
item reducer
и иfetchItemActionCreator
2.
const ItemComponent = ({ item , fetchItem}) => {
Это случайно?3. Только что добавлены создатель reducer и action. И да,
fetchItem
он случайно не был добавлен сюда в вопросе
Ответ №1:
Я хочу установить состояние загрузки для компонента
/** Action */
const getItem = () => dispatch => {
dispatch({ type: 'GET_ITEM_START' });
axios
.get('your api end point')
.then(res => {
const item = res.data;
dispatch({
type: 'GET_ITEM_SUCCESS',
payload: {
item,
},
});
})
.catch(error => {
dispatch({
type: 'GET_ITEM_FAIL',
payload: error,
});
});
};
/** Reducer */
const INITIAL_STATE = {
item: null,
error: '',
loading: false,
};
const itemReducer = (state = INITIAL_STATE, { type, payload }) => {
switch (type) {
case 'GET_ITEM_START':
return { ...state, error: '', loading: true };
case 'GET_ITEM_SUCCESS':
return { ...state, ...payload, loading: false };
case 'GET_ITEM_FAIL':
return { ...state, error: payload, loading: false };
default:
return state;
}
};
Тогда вы могли бы обрабатывать состояние загрузки в вашем компоненте
const ItemComponent = ({ fetchItem, item, loading, error }) => {
/** ... */
/**
Check for loading and show a spinner or anything like that
*/
useEffect(() => {
fetchItem(itemId);
}, []);
if (loading) return <ActivityIndicator />;
if (item) return <View>{/* renderItem */}</View>;
return null;
};
Комментарии:
1. Спасибо, что поделились этим @Hend El-Sahli. Есть ли способ сделать это с
useEffect
помощью? Вам нужно будет извлекать данные из самого компонента?2. Спасибо за обновление, @Hend El-Sahli. Мне было интересно, мне не нужно переходить
itemId
к массиву зависимостейuseEffect
?