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

Я пытаюсь получить некоторые данные в компоненте реакции с помощью хука useEffect. После первоначального рендеринга fetchItems() получает элементы и обновляет магазин. Однако items по-прежнему остается пустым объектом даже после обновления хранилища.

Я мог неправильно использовать useEffects. Как вы используете Redux с useEffects? Я хочу установить состояние загрузки для компонента, но поскольку компонент только отправляет действие для извлечения элементов (вместо прямого вызова API), он не знает, когда данные извлекаются, а хранилище обновляется, поэтому он может их вытащить .

Может кто-нибудь помочь выяснить, как убедиться, что объект items обновляется после получения саги и последующего обновления магазина?

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 - это создатель действия, который создает действие для отправки.
  • Мой редюсер и сага работают нормально, так как я могу видеть действия магазина и обновления в консоли.
  • Если я передам объект items в массив зависимостей для 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);

Заранее большое спасибо!


person Bovojon A    schedule 12.11.2020    source источник
comment
Не могли бы вы поделиться своими item reducer и и fetchItemActionCreator   -  person Hend El-Sahli    schedule 12.11.2020
comment
const ItemComponent = ({ item , fetchItem}) => { Это случайно?   -  person Hend El-Sahli    schedule 12.11.2020
comment
Просто добавил редуктор и создатель действий. И да, fetchItem был случайно не добавлен сюда в вопросе   -  person Bovojon A    schedule 13.11.2020


Ответы (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;
  };
person Hend El-Sahli    schedule 12.11.2020
comment
Спасибо, что поделились этим @Hend El-Sahli. Есть ли способ сделать это с useEffect? Вам нужно будет загружать данные в самом компоненте? - person Bovojon A; 13.11.2020
comment
Спасибо за обновление, @Hend El-Sahli. Мне было интересно, не нужно ли мне передавать itemId в массив зависимостей useEffect? - person Bovojon A; 16.11.2020