6

我正在使用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 更实用。

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

提前致谢

4

2 回答 2

14

我认为这有点多余,您最好使用其中一种,SWR 旨在将缓存用作本地状态,因为该状态存在于服务器上,它更加完善,并且使您无需冗长地管理状态中的每个操作,就像您在调度操作时必须与 redux 显式调用 API 调用一样。

使用这两种方式都无法达到 SWR 的目的,那么你最好只使用 Redux。一个好的规则是使用 SWR 管理服务器中的状态,使用 Redux 管理本地状态。

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

于 2021-04-22T17:45:23.583 回答
0

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

Redux 对于 props 的稳定性也需要一些努力。然而,人们可以使用提供的 useSelector + shallowEqual 来提取所需的最小值。这是 List 组件的 id 列表和卡片组件中的 row by 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} />)}
      </>)
    }
于 2021-06-21T10:20:57.583 回答