Redux架构:可在同一页面上使用新项目形式

时间:2016-08-17 16:17:35

标签: react-redux redux-form

我在单个屏幕上有项目列表。该列表从redux存储中获取并呈现为一组表单组件。在列表的底部,我有"添加新的"按钮。

在我的初始实现中,我使用了setState({newItem: {...})的容器组件。 当清除newItem并将新项目添加到redux项目时,这会产生视图闪烁的副作用。

    {items.map((item, index) =>
      <ItemForm
        key={index}
        formKey={index.toString()}
        initialValues={item}
        submitItem={this.handleUpdateItem.bind(this)}
        removeItem={() => this.handleRemoveItem(item.id)}
      />
    )}

    {newItem &&
      <ItemForm
        key="new"
        formKey="new"
        initialValues={newItem}
        submitItem={this.handleCreateItem.bind(this)}
        removeItem={() => this.handleRemoveNewItem()}
      />
    }

我认为更好的实现方法不是使用newItem而是在redux中处理新项目。但在这种情况下,我必须更改actions / reducers API,特别是CREATE_ITEM将不再附加项目,而是更新商店中的最后一项。

有什么方法可以减少闪烁,或者你有一些建议如何用redux做到这一点?特别是 - 我应该使用哪些动作/减速器来建立更好的解决方案?我是否应该在容器中进行API调用并简化redux操作?

对于我来说,actions / reducers API的复杂性来自于在redux中混合持久化(需要id来发出请求)而不是持久化对象(需要索引才能找到)。

这是我的redux模块:

import axios from 'axios';
import * as _ from 'lodash';

export const FETCH_ITEMS = 'items/FETCH_ITEMS';
export const CREATE_ITEM = 'items/CREATE_ITEM';
export const REMOVE_ITEM = 'items/REMOVE_ITEM';
export const UPDATE_ITEM = 'items/UPDATE_ITEM';

const initialState = {
  items: []
};

export default function reducer(state = initialState, action) {
  let index;

  switch (action.type) {
    case FETCH_ITEMS:
      return {
        ...state,
        items: action.items
      };
    case CREATE_ITEM: // would become "last item UPDATE_ITEM"
      return {
        ...state,
        items: [
          ...state.items,
          action.item
        ]
      };
    case REMOVE_ITEM:
      index = _.findIndex(state.items, {id: action.id});
      return {
        ...state,
        items: [
          ...state.items.slice(0, index),
          action.item,
          ...state.items.slice(index + 1)
        ]
      };
    case UPDATE_ITEM:
      index = _.findIndex(state.items, {id: action.item.id});
      return {
        ...state,
        items: [
          ...state.items.slice(0, index),
          action.item,
          ...state.items.slice(index + 1)
        ]
      };
    default:
      return state;
  }
}

export function fetchItems() {
  return function (dispatch) {
    return axios.get('/api/items')
      .then(res => {
        const items = res.data;
        dispatch({type: FETCH_ITEMS, items});
      })
  }
}

export function createItem(item) {
  return function (dispatch) {
    return axios.post('/api/items', item)
      .then(res => {
        const item = res.data.item;
        dispatch({type: CREATE_ITEM, item});
      })
  }
}

export function removeItem(id) {
  return function (dispatch) {
    return axios.delete(`/api/items/${id}`)
      .then(() => {
        dispatch({type: REMOVE_ITEM, id});
      });
  }
}

export function updateItem(item) {
  const {id, ...rest} = item;

  return function (dispatch) {
    return axios.put(`/api/items/${id}`, rest)
      .then(res => {
        const item = deserializeItem(res.data.item);
        dispatch({type: UPDATE_ITEM, item});
      })
  }
}

0 个答案:

没有答案