问题描述
我正在使用 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 旨在将缓存用作本地状态,因为该状态存在于服务器上,它更加充分,并且使您无需管理中的每一个操作详细的状态,就像您必须在任何时候调度操作时显式调用 API 调用的 redux 一样。
使用这两种方式都无法达到 SWR 的目的,那么您只使用 Redux 会更好。一个很好的规则是使用 SWR 来管理驻留在服务器中的状态,而 Redux 来管理本地状态。
我可以看到两者共存的一些场景,当你有一个非常复杂的数据操作,你必须经常修改和删除信息时,我认为这种情况会使用 redux 和 SWR 的 mutate 功能的一些混合。
,来自后端的响应可能包含一个项目列表。 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} />)}
</>)
}