Redux Thunk - Правильная реализация - PullRequest
0 голосов
/ 03 апреля 2019

Моя реализация избыточного потока приводит к переопределению данных массива.

Очевидно, что что-то не так в потоке, но я не могу понять это.

В основном у меня есть два компонента StringInstrument и UsersListedItems .

StringInstrument будет извлекать данные из БД (через axios) для получения списка владельцев элементов.

Для каждого владельца компонент UsersListedItems будетсоздан, и этот компонент также будет извлекать данные из БД (изображения) через идентификатор владельца.

Поэтому я бы сказал, что StringInstrument фактически создает UsersListedItems .

Вот код для StringInstrument :

if (this.props.error) {
        return <p>Sorry! There was an error loading the items</p>;
    }
    if (this.props.isLoading) {
        return <CircularProgress/>;
    }

     return (
        <div>
            <Grid container spacing={24}>
                {this.props.itemOwner.map((item, index) => (
                    <Grid item xs={6} sm={3} key={index}>
                        <UsersListedItems
                            ownerId={item.ownerId}
                            userName={item.userName}
                            categoryId={1}>
                        </UsersListedItems>
                    </Grid >)
                )}
            </Grid>
        </div>
    );
   }
  }

const mapStateToProps = (state) => {
return {
    itemOwner: state.itemOwner.data,
    isLoading: state.itemOwner.isLoading,
    error: state.itemOwner.error
}
 }

const mapDispatchToProps = (dispatch) => {
return {
    getItemOwners: (id) => dispatch(itemAction.getItemOwners(id))
  }

Вот как я реализовал действие и редуктор.

export function getItemOwner(state = initState, action) {
switch (action.type) {
    case GET_ITEM_OWNER_START:
        state = Object.assign({}, state, { isLoading: true });
        break;
    case GET_ITEM_OWNER_SUCCESS:
        state = Object.assign({}, state, { data: action.payload, isLoading: false });
        break;
    case GET_ITEM_OWNER_ERROR:
        state = Object.assign({}, state, { error: action.payload, isLoading: false });
        break;
}
return state;
 }

 export function getItems(state = initState, action) {
switch (action.type) {
    case GET_ITEMS_START:
        state = Object.assign({}, state, { isLoading: true });
        break;
    case GET_ITEMS_SUCCESS:
        state = Object.assign({}, state, { data: action.payload, isLoading: false });
        break;
    case GET_ITEMS_ERROR:
        state = Object.assign({}, state, { error: action.payload, isLoading: false });
        break;
}
return state;


export const getItemOwners = (categoryId) => {
return (dispatch, getState) => {
    //make async call to database
    dispatch({ type: GET_ITEM_OWNER_START });
    axios.get('api/items/owner/category/' + categoryId)
        .then(function (response) {
            dispatch({ type: GET_ITEM_OWNER_SUCCESS, payload: response.data });
        })
        .catch(function (error) {
            dispatch({ type: GET_ITEM_OWNER_ERROR, payload: error });
        });
}
 };

  export const getItems = (categoryId, ownerId) => {
   return (dispatch, getState) => {
    dispatch({ type: GET_ITEMS_START });
    axios.get('api/items/' + categoryId + '/' + ownerId)
        .then(function (response) {
            dispatch({ type: GET_ITEMS_SUCCESS, payload: response.data });
        })
        .catch(function (error) {
            dispatch({ type: GET_ITEMS_ERROR, payload: error });
        });
}

Я не уверен, какуправляйте \ управляйте потоком диспетчеров по порядку, чтобы он соответствовал структуре компонента без переопределения собранных данных.

Как вы можете видеть на прикрепленном изображении, 4 'GET_ITEM_SUCCESS' находятся в конце, и каждыйиз них переопределит следующий.

enter image description here

Надеюсь, я был ясен и извинился за этот длинный пример кода.

Спасибо

1 Ответ

0 голосов
/ 03 апреля 2019

Я думаю, проблема в том, что вы сохраняете только один из элементов в состоянии в любой момент времени, и каждый последующий вызов приводит к засорению контента в состоянии.Если я прав в этом предположении, то решение будет использовать categoryId и ownerId в качестве ключа для хранения данных в объекте, где значением будет полезная нагрузка.

Сначала вам нужно будет указатьcategoryId и ownerId в действии

export const getItems = (categoryId, ownerId) => (dispatch, getState) => {
  dispatch({ type: GET_ITEMS_START, categoryId, ownerId });
  axios.get('api/items/' + categoryId + '/' + ownerId)
    .then(function (response) {
      dispatch({ type: GET_ITEMS_SUCCESS, payload: response.data, categoryId, ownerId });
    })
    .catch(function (error) {
      dispatch({ type: GET_ITEMS_ERROR, payload: error, categoryId, ownerId });
    });

Далее вам необходимо обновить редуктор, чтобы назначить полезную нагрузку для объекта

const key = `${action.categoryId}-${action.ownerId}`; // unique key for the payload
switch (action.type) {
    case GET_ITEMS_START:
        state = Object.assign({}, state, { isLoading: true, data: Object.assign({}, state.data, {[key]: []}) });
        break;
    case GET_ITEMS_SUCCESS:
        state = Object.assign({}, state, { data: Object.assign({}, state.data, { [key]: action.payload }), isLoading: false });
        break;
    case GET_ITEMS_ERROR:
        state = Object.assign({}, state, { error: action.payload, isLoading: false });
        break;
}

Наконец, вам необходимо сопоставитьданные до состояния вашего компонента через реквизит (приставка).Затем вы можете получить доступ к элементам, используя те же ключевые элементы [${categoryId}-${ownerId}]

...