2

I'm using firebase database to store the data and I am mounting the data using the useEffect hook. But it gives me warning of missing dependency arrays.

Whenever I pass dependencies it goes into an infinite loop

const Channels = props => {
  const [channels, setChannels] = useState([]);
  const [firstLoad, setFirstLoad] = useState(false);

  useEffect(() => {
    let loadedChannels = [];

    firebase
      .database()
      .ref("channels")
      .on("child_added", snap => {
        loadedChannels.push(snap.val());
        setChannels(channels.concat(loadedChannels));
        setFirstLoad(true);
      });
  }, []);
}
4
  • Have you check that depency does not change when the useEffect is triggered? that way it will trigger the useEffect again. In a infinite lop Commented Jun 27, 2019 at 18:18
  • UseEffect has channels dependency which continuously changes inside it whenever I set Channels using setChannels(). That's why I don't pass channels as a dependency. Commented Jun 27, 2019 at 18:31
  • But it gives me warning of missing dependency arrays What dependencies are missing? Commented Jun 27, 2019 at 18:35
  • try using callback-based setter like setChannels(({ channels}) => ({channels: channels.concat(loadedChannels) }));(not really sure, that's why did not put an answer) Commented Jun 27, 2019 at 18:37

1 Answer 1

4

Edit: Looking at it again, the reason you're getting that error is because you're closing over the initial value of channels when your useEffect() runs the first time. So channels really should be in your dependency array because when that value changes, you would want the new value to be reflected in the state updates from then on. You're sort of trying to get around it with the loadedChannels array which is a weird anti-pattern.

I would actually recommend that you tweak it to something like this. Note how setChannels is now called with a function, which takes the actual up to date value of channels as an argument and lets you update the value without it being out of date due to a closure.

Note also how the useEffect() function returns another function that removes the Firebase event listener when the component unmounts!

const Channels = props => {
  const [channels, setChannels] = useState([]);
  const [firstLoad, setFirstLoad] = useState(false);

  useEffect(() => {
    function onFirebaseUpdate(snap) {
      setChannels((previousChannelsValue) => {
        return previousChannelsValue.concat(snap.val())
      });
      setFirstLoad(true);
    }

    firebase
      .database()
      .ref("channels")
      .on("child_added", onFirebaseUpdate);

    // You'll want to remove this listener when the component unmounts...
    return function() {
      firebase
        .database()
        .ref("channels")
        .off("child_added", onFirebaseUpdate);
    }
  }, []);
}

If you still get a warning, it's probably because either firebase or setChannels are references in the function and should be considered for addition to the dependency array. But in this case you (hopefully) know what you're doing and what's going on and can ignore the warning.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you so much for the above solution. It works for me
@AnjuBudhwan if it works for you please upvote and accept the answer! :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.