Home > Software engineering >  State updates only after changes are made to the code
State updates only after changes are made to the code

Time:12-20

I have a react native app which I get the user from the firebase firestore database. This works properly. But when I try to get the followers length from the user object it doesn't show or change it only changes when I make a change in the code and the app refreshes.

I read somewhere that useEffect runs on the second frame so I tried putting the code outside the useEffect but nothing changes


const [followingLength, setFollowingLength] = useState(0);
const [followersLength, setFollowersLength] = useState(0);

useEffect(() => {
  const userSub = onSnapshot(doc(firestore, "Users", userId), (doc) => {
            setUser(doc.data())

            if (user.following.length !== 0) {
                setFollowingLength(user.following.length)
            }

            if (user.followers.length !== 0) {
                setFollowersLength(user.followers.length)
            }
        });
});

<Text style={{ color: colors.white }}>{followingLength}</Text>
<Text style={{ color: colors.white }}>{followersLength}</Text>

CodePudding user response:

From the things I see definitelly:

Issue 1: Why your useEffect does not have any dependency array? In that case the code will be executed in every render which will be buggy and expensive.

Issue 2: Do you know that setUser does not update user object immediatelly and user in your if is "old" and closure captured?

Issue 3: Do you know that onSnapshot returns unsubscribe function that needs to be called to stop the listener. In your case you are adding 1 additional listener every render which is also buggy and expensive.

Im not 100% sure those combination of issues is exact the source of your problems, but they definitelly should be solved

Note: You can use useMemo to calculate following and followers.

const [user, setUser] = useState();
const followingLength = useMemo(() => {
  return user?.following?.length || 0;
}, [user]);

const followersLength = useMemo(() => {
  return user?.followers?.length || 0;
}, [user]);

useEffect(() => {
  const unsubscribe = onSnapshot(doc(firestore, "Users", userId), (doc) => {
    setUser(doc.data());

    // Or
    // const u = doc.data();
    // setUser(u);
    // setWhateverElse from "u", not "user"

  });

  return unsubscribe;
}, [userId]);
  • Related