Lamis Abouzina
Lamis Abouzina

Reputation: 409

useEffect causing an endless loop

i have a simple state and a function that runs in useEffect, i setup the useEffect second argument to my updating state but seems to run in an endless loop causing endless re-renders

const [file, setFile] = useState({audioFile: {} })

  const loadAudioFromPath = (path) => {
    import(`../components/Media/Resources/${path}`).then(audio =>
      setFile({
        audioFile: new Audio(audio),
      })
    );
  }

   useEffect(() => {
     loadAudioFromPath(resourceURI)
     console.log(file)
   }, [file])

i also tried

 useEffect(() => {
         loadAudioFromPath(resourceURI)
         console.log(file)
       }, [])

still same issue!

Upvotes: 0

Views: 85

Answers (5)

Diego Vinícius
Diego Vinícius

Reputation: 2243

This is happeing because you are watching for file changes, and you are making changes in file using setFile inside of useEffect, so you made the loop.

So to help you more, i need to know what you really is trying to achivie with that file.

1 - If you trying to just load the file once it is uploaded you can try something like:

const { file, setFile } = useState();
const { resourceURI, setResourceURI } = useState();

useEffect(() => {
    loadAudioFromPath(resourceURI)
}, [resourceURI])


const loadAudioFromPath = (path) => {
    import(`../components/Media/Resources/${path}`).then(audio =>
      setFile({
        audioFile: new Audio(audio),
      })
    );
  }

2 - If you trying to load the file just once (when the page is mounted)(Will do nothing if you change the file):

const { file, setFile } = useState();

useEffect(() => {
    loadAudioFromPath(resourceURI);        
}, [])

const loadAudioFromPath = (path) => {
    import(`../components/Media/Resources/${path}`).then(audio =>
        setFile({
            audioFile: new Audio(audio),
        })
    );
 }

3 - Or if you want to load the file if the current file is diferent than last one you can do something like i did in that answer -> A property is undefined - switching from class components to function hooks components in React

Upvotes: 0

Lamis Abouzina
Lamis Abouzina

Reputation: 409

inspired by dr.Telma i fixed it by putting the result of the promise in a separate state then using that to create a new Audio and set it in the other state

 const [file, setFile] = useState({audioFile: {} })
  const [comp, setComp] = useState({audioComp: {} })


  useEffect(() => {
    import(`../components/Media/Resources/${resourceURI}`).then(audio =>
      setComp({
        audioComp: audio.default,
      })
    ).then(()=>
    setFile({
      audioFile: new Audio(comp.audioComp),
    })
    )
  }, [])

Upvotes: 0

George Moringer
George Moringer

Reputation: 129

There must be some other issue in the code as:

useEffect(() => { loadAudioFromPath(resourceURI) console.log(file) }, [])

will only render once when the component loads. Happy to look into the rest of the code, if you add some more texture to the problem.

Upvotes: 0

Aib Syed
Aib Syed

Reputation: 3196

EDIT: Try and change your useEffect to something like this:

Basically, add a boolean. If the boolean state changes then useEffect will fire.

const [file, setFile] = useState({audioFile: {} })
const [bool, setBool] = useState(false)

  const loadAudioFromPath = (path) => {
    import(`../components/Media/Resources/${path}`).then(audio =>
      setFile({
        audioFile: new Audio(audio),
      })
    if (file.length !== 0) {
      setBool(true)
     }

    );
  }

   useEffect(() => {
     loadAudioFromPath(resourceURI)
     console.log(file)
   }, [bool])

Upvotes: 1

Ravi Garg
Ravi Garg

Reputation: 1534

useEffect(() => {
   loadAudioFromPath(resourceURI)
   console.log(file)
}, [])

Upvotes: 0

Related Questions