Компонент React не обновляется после изменений в хранилище Redux

#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 объект в массив зависимостей for useEffect , тогда будет бесконечный цикл, и страница продолжит повторный рендеринг.

Редуктор:

 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 ?