【问题标题】:Is it correct or good practice to use SWR together with Redux?将 SWR 与 Redux 一起使用是正确的还是好的做法?
【发布时间】:2021-03-29 12:56:43
【问题描述】:

我正在使用SWR

在我的代码中,我使用两者的交汇点,如下所示

const vehiclesStates = useSelector(({ vehiclesStates: state }) => state); // REDUX
const response = useFetch("/vehicles/states") // SWR
const dispatch = useDispatch(); // REDUX

// REDUX
useEffect(() => {
  if(response.data) dispatch(VehiclesStatesActions.setVehiclesStates(response.data.result))
}, [response.data, dispatch]);

if(response.error) return <div>ERROR - {response.error.toString()}</div> // SWR
else if(!response.data) return <div>LOADING</div> // SWR

// If there is a return I render my component
return (<></>)

在上面的这段摘录中,我使用我使用 SWR(与 axios 集成)返回的数据在 redux 中设置了我的组件状态。 这样,在需要使用相同数据的任何其他组件中,我只使用 redux 的 useSelect 导入它。

这边

const vehiclesStates = useSelector(({ vehiclesStates: state }) => state);

我发现它比通过在每个想要使用该数据的组件上调用 useFetch 来使用 SWR 更实用。

我的问题是:使用这种方式是正确的方式,还是会影响性能或其他什么?

提前致谢

【问题讨论】:

  • 为什么要使用带有 SWR 的 redux? Swr 为您处理所有缓存工作。如果您需要本地状态管理。我建议您使用 API 上下文。 Redux 会给你带来更多的复杂性。
  • 我之前使用了上下文,但是使用 redux 组织和存储结构我感觉更舒服:P

标签: javascript reactjs typescript react-redux swr


【解决方案1】:

我认为这有点多余,您最好使用其中一个,SWR 旨在将缓存用作本地状态,因为该状态存在于服务器上,它更合适,并且您可以从管理中的每一个操作中解放出来详细的状态,就像您必须在每次调度操作时显式调用 API 调用的 redux 一样。

使用这两种方式来击败 SWR 的目的,你会更好地使用 Redux。一个好的规则是使用 SWR 管理服务器中的状态,使用 Redux 管理本地状态。

我可以看到两者并存的一些场景,当你有一个非常复杂的数据操作,并且你必须经常修改和删除信息时,我认为这种情况将使用 redux 和 SWR 的 mutate 功能的一些组合。

【讨论】:

  • 很好的答案 - 从某种角度来看,SWR 通过其缓存为您的应用程序提供全局状态,其额外好处是能够使该缓存无效并使用新数据自动刷新它。
【解决方案2】:

来自后端的响应可能包含项目列表。 SWR 方法将强制您重绘所有使用列表中的项目的元素,或者创建一组相等比较器和/或上下文,这些比较器和/或上下文足够智能,可以判断 DOM 的哪个部分应该更新或不更新。

Redux 对于 props 的稳定性也需要一些努力。然而,人们可以使用提供的 useSelector + shallowEqual 来提取所需的最小值。这是 List 组件的 id 列表和卡片组件中按 id 排列的列表。

请检查代码。恕我直言,这两种方法不是直接竞争对手。

话虽如此,请记住有一些库(顺便说一下,Material-UI)可以为您管理列表。如果您使用其中之一,请使用他们的建议来优化重绘(如果需要)。

    import { FC } from "react";
    import { shallowEqual, useSelector } from "react-redux";
    import useSWR from "swr"

    interface CardInfo {
      id: number;
      name: string;
      price: number;
    };
    type RootState = Array<CardInfo>;

    declare const fetcher: () => Promise<CardInfo[]>

    const CardView: FC<CardInfo> = (p) => (<pre>{JSON.stringify(p)}</pre>);

    const CardById: FC<Pick<CardInfo, "id">> = ({ id }) => {
      const card = useSelector((rootState: RootState) => rootState.find((c) => c.id === id), shallowEqual)
      if (typeof card === "undefined") {
        return null;
      }
      return <CardView {...card} />
    }

    export const ListSwr: FC = () => {
      const { data } = useSWR(
        "/api/cards",
        fetcher,
        /*{compare: NO FANCY COMPARE HELPS 
          WHEN ONLY ONE OF MANY ITEMS CHANGED}*/
      );
      if (!Array.isArray(data)) {
        return null;
      }
      return (<>
        {data.map((c) => (<CardView key={c.id} {...c} />))}
      </>)
    }

    export const ListFromStore: FC = () => {
      const ids = useSelector((rootState: RootState) => rootState.map(e => e.id), shallowEqual)
      return (<>
        {ids.map((id) => <CardById key={id} id={id} />)}
      </>)
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-08
    • 2013-06-30
    • 2020-02-27
    • 1970-01-01
    • 2014-01-15
    • 1970-01-01
    • 2012-03-29
    • 2018-09-18
    相关资源
    最近更新 更多