0

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!

Lamis Abouzina
  • 369
  • 1
  • 3
  • 16
  • 2
    Drop `file` from your deps list and it should run just once. – jmargolisvt Nov 10 '20 at 19:17
  • @jmargolisvt that also doesn't work, same behaviour – Lamis Abouzina Nov 10 '20 at 19:20
  • If that's true, comment out the useEffect hook entirely and determine if your component is re-rendering for some other reason. The code you posted would definitely cause an infinite loop, but it doesn't mean you aren't causing a loop elsewhere. – jmargolisvt Nov 10 '20 at 19:29
  • @jmargolisvt the infinite loop stops once i comment out the useEffect hook ! – Lamis Abouzina Nov 10 '20 at 19:30
  • 1
    Even if you fixed the infinite loop, what is the end goal? The logic as-is would equate to - "When the file updates, update the file", which obviously makes an infinite loop. So unless I'm misunderstanding the desired outcome, this is more of a logic error than anything. – Brian Thompson Nov 10 '20 at 19:40

5 Answers5

1

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])
Aib Syed
  • 3,118
  • 2
  • 19
  • 30
0
useEffect(() => {
   loadAudioFromPath(resourceURI)
   console.log(file)
}, [])
Ravi Garg
  • 1,378
  • 12
  • 23
0

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.

0

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),
    })
    )
  }, [])
Lamis Abouzina
  • 369
  • 1
  • 3
  • 16
0

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

Diego Vinícius
  • 2,125
  • 1
  • 12
  • 23