React Hooks useEffect even with empty dependency runs more than once

Asked

Viewed 2,673 times

1

I am using the React hook useEffect to fetch the data in an API, when the page loads, useEffect runs 2 times, but should run only once, since I declared the second parameter (dependency array) as empty array, in inspecting element > network > XHR, you can see that 2 requisitions were made.

const fetchWelcomeContent = async () => await api.get('welcome/getWelcomeContent').then(response => {
    setEditorState(EditorState.createWithContent(convertFromRaw(JSON.parse(response.data.data))))
    setIsLoading(false)
    toastToggle('fas fa-times', 'Carregado')
}).catch(error => {
    toastToggle('fas fa-times', error.message)
})

useEffect(() => {
    fetchWelcomeContent()
}, [])

And still on the console is displayed the following message:

 Line 57:8:  React Hook useEffect has a missing dependency: 'fetchWelcomeContent'. Either include it or remove the dependency array  react-hooks/exhaustive-deps

If I remove the dependency array or place 'fetchWelcomeContent' as dependency, it results in an infinite loop, if I put the function inside use Effect gives another error.

import React, { useState, useEffect } from 'react'
import * as jwt_decode from 'jwt-decode';
import api from '../../services/api'
import {getToken} from '../../services/auth'
import { EditorState, convertToRaw, convertFromRaw } from 'draft-js'

import ReactPlaceholder from 'react-placeholder'
import 'react-placeholder/lib/reactPlaceholder.css'

import { Editor } from 'react-draft-wysiwyg'
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css'

import XDKHead from '../../components/XDKHead'
import XDKToast from '../../components/XDKToast'
import XDKButton from '../../components/XDKButton'
import './index.css'


const Welcome = () => {

    const [ editorState, setEditorState ] = useState(EditorState.createEmpty())
    const [ isLoading, setIsLoading ] = useState(true)
    const [ toast, setToast ] = useState({ isShowing: false, type: '', message: '' })

    const toastToggle = (
        toggleType = toast.type,
        toggleMessage = toast.message
    ) => setToast({
        isShowing:!toast.isShowing,
        type: toggleType,
        message: toggleMessage
    })

    const saveWelcome = async () => {
        await api.post('welcome/setWelcomeContent', `{
            "user":"${jwt_decode(getToken()).sub}",
            "editorContent":${JSON.stringify(convertToRaw(editorState.getCurrentContent()))}
        }`).then(response => {
            //console.log(response)
        }).catch(error => {
            console.log('error: ', error)
        })
    }

    useEffect(() => {
        const setWelcomeContent = async () => {
            await api.get('welcome/getWelcomeContent').then(response => {
                setEditorState(EditorState.createWithContent(convertFromRaw(JSON.parse(response.data.data))))
                setIsLoading(false)
                toastToggle('fas fa-times', 'Carregado')
            }).catch(error => {
                toastToggle('fas fa-times', error.message)
            })
        }

    }, [])

    return (
        <>private code here...</>
    ) // return
} // Welcome

export default Welcome
  • Edit your question by placing the complete code of your component. ([Edit])

  • The javascript code is misspelled on the async and await ...

1 answer

1


You are using async and await to solve the promisse and then using the then and thereby generating duplicity in the request, but, solve so:

function fetchWelcomeContent() {
    api.get('welcome/getWelcomeContent')
        .then(response => {
            setEditorState(EditorState
                .createWithContent(
                    convertFromRaw(JSON.parse(response.data.data))
                )
            )
            setIsLoading(false)
            toastToggle('fas fa-times', 'Carregado')
        });
}

useEffect(() => {
    fetchWelcomeContent()
},[])

or if you still want to use async and await:

async function fetchWelcomeContent() {
    var response = await api.get('welcome/getWelcomeContent');
    setEditorState(
        EditorState
            .createWithContent(
                convertFromRaw(JSON.parse(response.data)
            )
        )
    )
    setIsLoading(false)
    toastToggle('fas fa-times', 'Carregado')
}

useEffect(() => {
    fetchWelcomeContent()
},[])

I prefer to put the traditional way is easier to understand, it is clear ...

  • 1

    novic, it wouldn’t be interesting to declare the function fetchWelcomeContent() inside the body of useEffect? Otherwise, I believe the error message indicated in the question persists

  • @Yoyo can be declared inside or outside, it changes nothing regarding execution. The problem was how he wrote the function code that was the problem

Browser other questions tagged

You are not signed in. Login or sign up in order to post.