0

Hi friends I am having trouble for updating state after fetch data from api. Can anyone help me to figure it out. I am new in typescript btw.

type FrequentlySearches = {
    value: string;
    count: string;
};

const initialFrequentlySearch: FrequentlySearches[] = [{
    value: '',
    count: '',
}];

export const GetFrequentlySearches = () => {

    const [data, dataSet] = useState(initialFrequentlySearch);

    const fetchFrequentlySearches = useCallback(async () => {
        let response = await fetch(url_pathname)
        let datas = await response.json()
        for (const key in datas) {
            // how  to update the state here !!!
            dataSet({
                value: datas[key].value,
                count: datas[key].count
            })
        }

    }, [url_pathname])


    useEffect(() => {
        fetchFrequentlySearches()
    }, [url_pathname])

};
undef1ned
  • 3
  • 2
  • it shows that >>> Argument of type '{ value: any; count: any; }' is not assignable to parameter of type 'SetStateAction'. Object literal may only specify known properties, and 'value' does not exist in type 'SetStateAction'.ts(2345) – undef1ned May 14 '21 at 17:19
  • It looks like your data comes back in the shape you need but you're trying to iterate over it and set it as an individual object each time instead of an array. Why not just do `dataSet(datas)` ? – LMulvey May 14 '21 at 17:23

1 Answers1

0

You need to

(1) Type the fetch properly, see here

(2) The data is an array of objects, so

        dataSet({
            value: datas[key].value,
            count: datas[key].count
        })

doesn't make much sense - pass an array of objects to the state setter function instead.

It'd probably be easier to just take the object values of the response as an array - no need to iterate manually.

The useCallback is completely superfluous too.

export const GetFrequentlySearches = () => {
    const [data, setData] = useState(initialFrequentlySearch);
    useEffect(() => {
        fetch(url_pathname)
        .then((response => response.json()))
        .then((datasUntyped) => {
            const datas = datasUntyped as FrequentlySearches[];
            setData(Object.values(datas));
        })
        // .catch(handleErrors);
    }, [url_pathname])

}

If the API result is an array of objects and not an object of objects, then you don't need Object.values at all, just do

setData(datas);

If the API result contains other object properties you need to exclude, map the array to remove them first:

setData(
  Object.values(datas)
    .map(obj => ({ value: obj.value, count: obj.count }))
);
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320