Redux - 我应该从状态或 api 调用中获取产品详细信息吗?

Posted

技术标签:

【中文标题】Redux - 我应该从状态或 api 调用中获取产品详细信息吗?【英文标题】:Redux - should I get product details from state or api call? 【发布时间】:2021-08-02 14:38:37 【问题描述】:

在一个 react 和 redux 应用程序中,我获取了用户的所有产品并将其存储在用户首次登录并进入主页时的状态。然后,用户可以查看其产品的某个单独页面,并可能在其中编辑内容。

因此,在详细信息页面上,我可以使用状态列表中已存储的产品。它避免了需要进行另一个 api 调用,据我所知,这是“反应方式”。它快速高效。

但我也看到了这样做的缺点:

如果用户直接访问 hi.com/product/1 的 url,则该商店尚未填充他的产品数据,则该商店不可用。那该怎么办?有条件地在商店中加载当前产品的数据?重定向到主页?听起来很乱。 它会强制系统最初加载每个产品的详细信息。产品不多就好,但多就不好说了。更多数据要通过网络发送,更多数据要存储。

【问题讨论】:

【参考方案1】:

要处理这种特定情况,您可以为您的路由添加 Content Guard(或 Route Guard),专门检查您所需的数据是否存在于 Redux 状态。

你可以在这里使用一个不错的库react-router-guards

或者您始终可以创建自己的逻辑功能组件,以根据您的页面管理您的路由和基本 API 调用

举例

如果您直接访问 hi.com/product/1

1) 当你使用 react-router-guards 时

const requireStates = (to, from, next) => 
  if (to.meta.auth) 
    if (getIsLoggedIn()) 
      let actualPath = to.location.pathname.split("/");
      if(actualPath[1] === "product") 
       if(isProductAPIDataPresent)// here check if redux state have that particular data present
        
          next();
         else 
           fetch(); // get Product API data 
           store(); // store it in redux states
           next();
        
       else 
           next();
      
    
    next.redirect('/login');
   else 
    next();
  
;

const App = () => (
  <BrowserRouter>
    <GuardProvider guards=[requireStates] loading=Loading error=NotFound>
      <Switch>
        <GuardedRoute path="/product/:productID" exact component=Product meta= auth: true  />
        <GuardedRoute path="/home" exact component=Home meta= auth: true  />
        <GuardedRoute path="/login" component=Login />
      </Switch>
    </GuardProvider>
  </BrowserRouter>
);

2) 当你想构建自己的功能逻辑时(你可以只做一个功能组件,它会返回一些基本的真假情况)

   const requireStates = (tprops) => 
             let next = 
               isAllowed: true,
               newLocation: "/",
             
              if (props.meta.auth) 
                if (getIsLoggedIn()) 
                  let actualPath = props.location.pathname.split("/");
                  if(actualPath[1] === "product") 
                    if(isProductAPIDataPresent)// here check if redux state have that particular data present
                    
                      return next;
                     else 
                       fetch(); // get Product API data 
                       store(); // store it in redux states
                       return next;
                    
                  else 
                  return next;
                
                
       
                next.isAllowed = false;
                next.newLocation = "/login"
                return next;
               else 
                return next;
              
            ;

您还需要制作一个父组件(所有路由通用,它可以是布局组件),它将在继续处理该特定路由组件或子组件之前呈现

所以在那个父组件中,你可以像这样注入上面的逻辑

  componentDidMount = async () => 
    await requireStates(this.props).then((result) => 
      if (!result.isAllowed) 
        window.location.replace(result.newLocation);
      
    );
  ;

注意*:对于第二种解决方案,您可以通过多种方式实现所需目标

【讨论】:

非常有趣和详细的答案,谢谢!我的问题中的第二点呢,发送大量我可能不需要的数据不是性能问题吗? 这里我认为你已经将数据直接存储在一个单一的 redux 状态,当你有大量数据或者可能是深度嵌套数据的情况下,你将面临从中获取特定数据的性能问题(您可以通过使用各种有效的算法来解决这个问题)。所以在这个特殊的情况下,我个人使用 IndexDB 来存储和管理我的状态。 IndexDB 通过索引帮助存储您的数据,稍后,您可以有效地获取它,您还可以使用各种方法保护此存储以确保数据安全。考虑到您的数据复杂性,您可以处理您的案例。

以上是关于Redux - 我应该从状态或 api 调用中获取产品详细信息吗?的主要内容,如果未能解决你的问题,请参考以下文章

意外的 redux 操作调度行为

在 Redux 中更改 props 但不更改状态的 API 调用应该放在哪里?

何时使用 Redux-saga / Redux thunk 何时不使用? [关闭]

React/Redux - 你啥时候应该从 API 获取新数据来更新你的商店?

使用 get API 调用反应全局状态/道具(没有 Redux)

获取组件(窗口小部件)中相应的redux存储状态更新的数据