Search code examples
reactjsasync-awaitfetch-apiuse-effect

ReactJs can't get async content form api call in useEffect and use it later in component


I'm lost. I've tried almost all I know. In my other component, similar process works fine, but in this one there is something obviously wrong implemented. I have a Context Provider, and set two values to share, a function to call an Api and retrieve a list of contacts (getContactsList), and a variable where I put that list of contacts (contactsList). I call getContactsList in useEffect. Later, I can use contactsList variable, but is always an empty array. I know that the problem is related to Promises and async functions maybe, but I can't find the mistake in my code.

I left here a copy of the components, starting for the view component that has the problem:

Detail Component:

function ContactDetail() {
    
    const { getContactsList, contactsList } = useContext(ContactsContext);
    const { id } = useParams();
    useEffect(() => { getContactsList().catch(null) }, []);

    const contact = contactsList?.filter(c => {
        return (Number(c.id) === Number(id))
    });

    return (
        <div>
            {contact? "contact finded" : "contact not finded"}
        </div>
    );
}

ApiCall

async function apiCall (
    url,
    method = "get",
    body,
    headers)
    {
       try {
           const response = await fetch(url, {
            method,
            body,
            headers
        });

        const r = await response.json();
        return r;
    }
    catch (err) {
        Promise.reject(err);
    }
    }

Provider

function ContactsProvider({ children }) {

    const [ contactsList,setContactsList ] = useState([]);

    const getContactsList = async () => {
        try {
            const contactsResult = await apiCall("https://fakeurl.com");
            setContactsList(contactsResult);
        }
        catch(err) {
            setContactsList([]);
        }};

    return (
        <ContactsContext.Provider value={{getContactsList, contactsList}}>
            {children}
        </ContactsContext.Provider>
    );
}

Also, the code is in my GitHub: https://github.com/thenablyn/local-search-browser.git


Solution

  • The error was that I forgot to get the first element when I did the array.filter() method. It's a Jr mistake.

    The code in that assignment has to be like this:

    const [contact] = contactsList.filter(...); //this get the first element and assign to constant "contact"