繁体   English   中英

反应:如何使用 useEffect 只打一次 API

[英]React: How to hit API only once using useEffect

我在 API 调用中有一组对象,我是从useEffect调用的。 基本上我想要的是,我只想打一次 API 并将数组设置在localStorage中。

现在,如果 localStorage 有一些与之相关的数据,则使用useState的集合数组将通过localStorage在其中设置,否则如果它不包含任何与之相关的项目,那么它将再次访问 API 以获取数组并设置为localStorage

到目前为止我所做的代码是:

const [loadedg, setloadedg] = useState(false);
const [domainListGroupItems, setdomainListGroupItems] = useState([]);

    useEffect(() => {
        //---------->Groups Lists<----------------
        if(!loadedg) {
            setdomainListGroupItems(JSON.parse(localStorage.getItem('leftgroup')))
        }else{
            ApiService(leftgroups).then((response) => {
                if (response.statusCode === 1) {
                    const item = response.domainGroupList
                    localStorage.setItem('leftgroup', JSON.stringify(item));
                    setloadedg(true);
                    console.log(item);
                } else {
                    setloadedg(false);
                }
            })
            .catch((error) => {
                console.log(error)
            })
        }
    }, [loadedg]);

我在这里使用的概念基本上是使用我认为应该使用的 boolean 条件。 但如果它可以在不使用 boolean 值的情况下完成,那对我来说会很棒。

我将如何解决这个问题? 谢谢你。

您可以使用值初始化 state

const [domainListGroupItems, setdomainListGroupItems] = useState(JSON.parse(localStorage.getItem('leftgroup')));

然后,在您的useEffect中,只需检查domainListGroupItems是否为 null

useEffect(() => {
  if (domainListGroupItems) return; // already set from localStorage

  ApiService(leftgroups).then((response) => { .... })

}, [domainListGroupItems]);

为了限制useEffect只触发一次,您可以从依赖数组中删除加载的g,现在它将简单地检查数据是否已经存在于本地存储中,如果没有,它将获取数据并将数据设置在本地存储中.

有关 useEffect 和依赖数组的文章链接

希望它能解决你的问题。

因此,您想使用 localStorage 作为客户端缓存,设置到期日期比检查密钥是否存在更有趣。 在下面的代码片段中,我将localStorage填充为ls并将 API 调用设置为带有setTimeoutpromise用于测试目的。

我将 apiCall 效果提取为独立的,因此您可以在任何地方使用它,并给它一个skip参数。 在代码段中,如果本地存储缓存的日期少于 7 天,则将跳过调用。 您可以编辑片段并取消注释 2 行以测试缓存是最近时会发生什么。 请务必将代码段扩展为“整页”,否则控制台日志会隐藏 localStorage 值:)

 const useState = React.useState, useEffect = React.useEffect; // network call shim function ApiService() { return new Promise((resolve, reject) => { setTimeout(() => { try { resolve({ statusCode: 1, domainGroupList: ['Hello','World'] }); } catch (err) { reject(new Error('500 Server Error')); } }, 1000); }); } // localstorage shim const ls = Object.create({ getItem(key) { return this[key]; }, setItem(key, value) { this[key] = value; } }); // comment out to see what happens when ls has been populated less than 7d ago // ls.setItem('lastfetch', new Date().toISOString()); // ls.setItem('groupleft', []); function isLessThan7DaysAgo(date) { const today = new Date(); return date > new Date(today.setDate(today.getDate()-7)); } const apiCallEffect = (onLoad, skip) => () => { if (skip) return; ApiService().then((response) => { if (response.statusCode === 1) { const items = response.domainGroupList; ls.setItem('leftgroup', JSON.stringify(items)); ls.setItem('lastfetch', new Date().toISOString()); if (onLoad) onLoad(items); } }).catch((error) => { console.log(error.message) }); } const App = ({ initialItems, onLoad }) => { const skip = ls.getItem('lastfetch') && isLessThan7DaysAgo(new Date(ls.getItem('lastfetch'))); const [loaded, setloaded] = useState(skip); const [groupItems, setGroupItems] = useState(initialItems); console.log(skip? 'skipping fetch, getting from ls': 'doing fetch, storing in ls'); useEffect(apiCallEffect((items) => { setloaded(true); setGroupItems(items); }, skip), [groupItems]); return <div> { loaded? <ul>{groupItems.map(x => (<li>{x}</li>)) }</ul>: <div>Loading...</div> } <strong>In localstorage</strong><br/> <pre>{JSON.stringify(ls, null, 2)}</pre> </div>; }; const storedDomainListGroupItems = ls.getItem('leftgroup') || []; ReactDOM.render(<App initialItems={storedDomainListGroupItems}/>, document.getElementById('app'));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script> <strong>In app:</strong> <div id="app"></div>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM