在Redux中复制状态

时间:2018-01-23 03:38:40

标签: architecture redux

让我们假设你有一个使用Redux的书籍应用程序,其中包含一些功能:

  • 购买书籍
  • 有一份书愿望清单
  • 维护您拥有的图书清单
  • 向朋友发送推荐
  • 评论书籍

现在让我们说所有这些不同的模块,以及所有这些模块的共同特征是能够搜索书籍(即搜索要购买的书籍,添加到心​​愿单的书籍,要查看的书籍)等等。)

这些搜索结果将存储在状态树的多个切片中。

状态树的示例可能如下所示:

{
  bookStore: {
    booksSearchResults: [],
    ...,
  },
  wishlist: {
    booksSearchResults: [],
    ...,
  },
  reviews: {
    newReview: {
      booksSearchResults: [],
      ...,
    },
    ...
  },
  ...
}

有关于管理此类事情的最佳做法吗?是否只是拥有一个booksSearch状态片并通过共享组件进行管理?

如果您可能需要在同一屏幕上的多个位置搜索图书(例如,除了应用程序主要部分中的搜索组件外,您可能在导航栏中有自动完成搜索功能)?< / p>

是另一种重用搜索逻辑的方法,并以某种方式让它更新状态的不同部分(如果有的话,是否存在实现此目的的东西)?

4 个答案:

答案 0 :(得分:2)

redux应用程序中的可重用组件有一个很好的模式,对您有用。这假设搜索从redux的角度使用相同的api和逻辑,并为逻辑使用一个或多个可重用的组件。

在此示例中,我将<AutoCompleteSearch /><FullSearch />用作UI组件,每个组件都可以在应用程序或同一页面中多次出现。

此处使用的模式是为每个组件分配一个唯一的道具,此处命名为searchId: string,例如<AutoCompleteSearch searchId="wishlist" />

然后,组件在所有与搜索相关的操作的有效载荷中传递此id,例如,

{
  type: SEARCH,
  payload: {
    term: "Harry Potter",
    searchId: "wishlist",
  }
}

搜索缩减器的结构为searchId为关键字的地图。 redux状态的示例:

{
  wishlist: {
    inProgress: true,
    searchTerm: "Harry Potter",
    results: [],
  },
  reviews: {
    inProgress: false,
    searchTerm: "",
    results: [],
  },
}

然后reducer选择要处理的状态部分:

const reducer = (state, action) => {
  switch(action.type) {
    case SEARCH:
      return {
        ...state,
        [action.payload.searchId]: {
          inProgress: true,
          searchTerm: action.payload.searchTerm,
          results: [],
        }
      };
    default:
      return state;
  }

对于使用此模式进行数据加载的现成库,请参阅redux-autoloader

答案 1 :(得分:2)

我有两条建议:

  1. 规范您的商店。
  2. 不要将您的搜索结果存储在redux中。
  3. 正常​​化

    这是有据可查的,所以我在这里不太深入。可以说,规范化您的商店将是灵活的,并帮助您推理您的应用程序。您可以将您的商店视为服务器端数据库,并且与您根据视图定制州的每个部分相比,它将更具可重用性。

    您可以通过以下方式为您的应用做到这一点:

    {
      books: { 
        bookId: { 
          bookDetails,
          reviews: [ reviewId ],
          ownedBy: [ userId ],
          wishlistedBy: [ userId ],
          recommendations: [ recommendationId ]
        }
      },
      users: {
        userId: { 
          userDetails,
          reviews: [ reviewId ],
          wishlist: [ bookId ],
          ownedBooks: [ bookId ],
          friends: [ userId ],
          sentRecommendations: [ recommendationId ],
          receivedRecommendations: [ recommendationId ]
        }
      },
      reviews: {
        reviewId: {
          bookId,
          userId,
          reviewDetails
        }
      },
      recommendations: {
        recommendationId: {
          sender: userId,
          recipient: userId,
          bookId,
          recommendationDetails
        }
      }
    }
    

    你可能不需要所有这些关系,所以不要觉得你必须实现所有这些。但是从类似于此的基础开始将使以后更容易添加功能。

    资源:

    放置搜索结果的位置

    搜索结果更多地是视图详细信息,而不是数据问题。您可能需要存储搜索的历史记录,在这种情况下,您可以为搜索添加减速器:

    {
      searches: [
        {
          searchTerm,
          searchDetails
        }
      ]
    }
    

    但即使在这种情况下,我也不认为我会存储搜索结果。存储结果将限制几种情况下的功能。

    1. 当用户搜索时,会添加新书,除非您重新运行搜索(否定存储结果的有用性),否则您将无法在后续搜索中找到新书。
    2. 搜索需要快速并且存储结果只会加速重复搜索(这可能不太常见)。
    3. 所以,我认为结果是一个观点细节 - 或者正如James K. Nelson所说的那样,&#34;控制状态&#34; (阅读:The 5 Types of React Application State)。您的问题并未说明您正在使用哪个视图库(如果有),但无论您是否使用React,此处的概念都应适用。

      搜索结果应由视图计算。视图将接收用户输入,可能获取数据(将添加到存储中),在Redux状态下运行一些过滤器功能,并显示结果。

答案 2 :(得分:0)

如果您能够重复使用搜索结果,意味着搜索查询相同或跨组件共享,那么最好使用共享组件。如果不是,建议将搜索和搜索结果分开并与上下文相关。

参见唐与他的todos样本分享的例子。他为所有Todos 已完成Todos Active Todos 创建了三个不同的列表。

答案 3 :(得分:0)

我认为答案取决于你的需要:

  1. 共享搜索 - 例如在任何上下文中搜索过的项目。
  2. Uniqe搜索 - 例如在特定上下文中搜索的项目。
  3. 如果你想通过第一种情况进行自动转发,我建议将所有搜索数组合起来,并将数据存储在提供更多deatils的对象中,例如searchContext等。 如果您希望通过第二种情况自动完成,则其他上下文的搜索结果不相关,因此建议对任何搜索上下文使用单独的数组。