React中如何避免useSWR随state变化触发不必要重渲染?
解决useSWR在组件状态变化时的不必要重渲染问题
当open状态切换触发组件重渲染时,console.log(data)执行并不代表useSWR重新请求了数据——这只是组件重渲染带来的日志输出。如果要避免依赖useSWR的部分随open变化而无意义重渲染,或者减少整体重渲染开销,可以试试以下几种方法:
- 拆分组件,隔离重渲染范围
把使用useSWR获取数据的逻辑和模态框控制逻辑拆成独立组件。这样open状态变化时,只有负责模态框的父组件重渲染,数据组件除非data更新,否则不会触发重渲染:
// 独立的数据展示组件,只关心useSWR返回的数据 const DataDisplay = () => { const { data } = useSWR('my_key_swr', fetcher); console.log(data); return <div>{data?.content}</div>; }; // 父组件仅负责模态框状态管理 const ParentComponent = () => { const [open, setOpen] = useState(false); return ( <> <button onClick={() => setOpen(!open)}>打开模态框</button> {open && <Modal><DataDisplay /></Modal>} </> ); };
- 用React.memo包裹数据组件
如果不想拆分组件,可通过React.memo让数据组件仅在props变化时重渲染。注意:如果组件内部有自己的状态(比如open),状态变化仍会触发重渲染,所以更适合把纯数据展示的子组件用memo包裹:
// 用React.memo包裹,避免无意义重渲染 const DataDisplay = React.memo(() => { const { data } = useSWR('my_key_swr', fetcher); console.log(data); return <div>{data?.content}</div>; }); const ParentComponent = () => { const [open, setOpen] = useState(false); return ( <> <button onClick={() => setOpen(!open)}>打开模态框</button> <DataDisplay /> {open && <Modal />} </> ); };
- 确保fetcher函数稳定,避免不必要的重新请求
如果fetcher函数在每次组件重渲染时都被重新创建,useSWR可能会误判为需要重新请求数据。解决方法是把fetcher定义在组件外部,或者用useCallback包裹并指定正确的依赖项:
// 定义在组件外部,保证函数引用稳定 const fetcher = async (url) => { const res = await fetch(url); return res.json(); }; const MyComponent = () => { const [open, setOpen] = useState(false); const { data } = useSWR('my_key_swr', fetcher); console.log(data); return ( // ...你的组件内容 ); };
如果fetcher依赖组件内部的值,用useCallback包裹:
const MyComponent = () => { const [open, setOpen] = useState(false); const userId = useSelector(state => state.user.id); // 仅当userId变化时才重新创建fetcher const fetcher = useCallback(async () => { const res = await fetch(`/api/data/${userId}`); return res.json(); }, [userId]); const { data } = useSWR('my_key_swr', fetcher); console.log(data); return ( // ...你的组件内容 ); };
- 仅在data真正变化时打印日志
如果只是不想看到组件重渲染时的重复日志,而非阻止重渲染,可以用useEffect监听data的变化,只在data更新时打印:
const MyComponent = () => { const [open, setOpen] = useState(false); const { data } = useSWR('my_key_swr', fetcher); useEffect(() => { console.log(data); // 只有data真正变化时才执行 }, [data]); return ( // ...你的组件内容 ); };
内容的提问来源于stack exchange,提问作者Epple
相关产品推荐
相关产品推荐

