1

I have a custom hook that gets file data from the cache api based on an url. The hook works fine.

Problem is that I get a response back and I need to parse this data before I can use the fabric tag picker. and I also only want to parse that data when the user starts typing. I know that the prop "filterSuggestedTags" accepts a promise like call and we can fetch data before there.

You will see that I am using a fetch inside the filterSuggestedTags and that ensures to fetch the data from the url before showing the results, plus it shows the loader as well: https://codepen.io/deleite/pen/MWjBMjY?editors=1111

So given the code below and the fact that my useCache gives my a fetch response as state:

const filterSuggestedTags = async (filterText: string, tagList: ITag[]) => {
    if (filterText) {
      // how can I await the response state? before I can parse the data 
      return (await /* resp should be the state from the custom hook*/ resp.json()).map(item => ({ key: item.id, name: item.title }));
    } else return []
  };
skyboyer
  • 22,209
  • 7
  • 57
  • 64
Ricardo Silva
  • 1,221
  • 9
  • 19

1 Answers1

0

Be warned, this is not tested, nor am I of the opinion this the best thing to do, just some thoughts.

EDIT: After some thinking, this might be better

This might save you some headaches with old sate, updates.

const useFilterSuggestedTags = async (filterText: string, tagList: ITag[]) => {
    const [data, setData] = useState<WhateverYouReturn[]>([]);

    useEffect(() => {
        const controller = new AbortController();

        if (filterText) fetchData();
        
        async function fetchData() {
            try {
                const resp = await fetch('url', {signal: controller.signal});
                const json = await resp.json();

                if (!controller.signal.aborted) {
                    setData(json.map(_ => ({ key: _.id, name: _.title, })));
                }
            } catch(e) {
                if (!(e instanceof AbortError)) throw e
            }
        }

        //  If your effect returns a function, React will run it when it is time to
        // clean up:
        return controller.abort;
    }, [filterText, tagList])

    return data;
};

Old Answer

How about

const useFilterSuggestedTags = async (filterText: string, tagList: ITag[]) => {
    const [data, setData] = useState<WhateverYouReturn[]>([]);

    if (filterText) fetchData();

    return data;

    async function fetchData() {
        const resp = await {}; // Obviously fetch something
        const json = await resp.json();

        // I assume you also need to filter them, but I guess you know how
        // to do that :P

        setData(json.map(_ => ({ key: _.id, name: _.title, })));
    }
};

Little notice: It is good practice to name your hooks use[...]. At least that is what they (and the react-hooks es-lint plugin) suggest.

Elias
  • 3,592
  • 2
  • 19
  • 42
  • Thanks, I have named it useCacheAPI. I will try to check your answer today and accept if works. What I did at the moment was to await the items to be parsed, which works but not what I wanted. I wanted to parse the data from the cache only when they try to search for it. Now it is almost unnoticeable but if I have multiple fields with large data set it will take ages to load all components and eat up a lot of memory. – Ricardo Silva Jan 14 '21 at 12:53
  • @RicardoSilva Normally it is not recommended to block other code, but hey, if it works :P just don't use it in production lol :D – Elias Jan 14 '21 at 12:56
  • yes, that is what I want to avoid it should not block anything just await the data to be parsed to render the suggestion in the fields that depends on that data. So either by leave the tagpicker component loading or awaiting a promise all other controls in the form should be available to be filled. – Ricardo Silva Jan 14 '21 at 13:00
  • I would go with the first one, but if it only makes sense to show the complete app, I'd recommend you take a look at [Promise.all](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) – Elias Jan 15 '21 at 06:17