繁体   English   中英

无法对未安装的组件 useEffect 错误执行 React state 更新

[英]Can't perform a React state update on an unmounted component useEffect error

我有这段代码,我在其中获取数据并将其传递给组件。 然后这个子组件渲染我制作的数据,这样当用户从顶部下拉时,组件会刷新,但是每当我first time only刷新时,我都会收到错误

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

这是代码:

function FolloweringScreens({
  data,
  screen,
  username,
  navigation,
  noMoreData,
  setLoadingMore,
  lastVisible,
  setNoMoreData,
  setLastVisible,
  setfollowingData,
  loadingMore,
  setLoading,
  currentuser,
}) {
  const [stateData, setStateData] = useState();
  const [refresh, setRefresh] = useState(false);

  useEffect(() => {
    const setState = () => setStateData(data);
    return setState();
  }, [data, refresh]);

  // Refresh
  const handleFetch = () => {
    setRefresh(true);
    const cleanup = fetchData(
      username,
      setfollowingData,
      setLoading,
      setLastVisible,
      setNoMoreData,
      setRefresh,
      screen,
      currentuser,
    );
    return cleanup;
  };

  return (
    <>
      <FlatList
        refreshing={refresh}
        onRefresh={handleFetch}
        data={stateData}
        keyExtractor={(i, index) => index.toString()}
        renderItem={({item, index}) => {
          return (
            <>
                 { Using my data here }
            </>
          );
        }}
      />
    </>
  );
}

export default FolloweringScreens;

这是 fetchData function:

export const fetchData = (
  username,
  setfollowingData,
  setLoading,
  setLastVisible,
  setNoMoreData,
  setRefresh,
  screen,
  currentuser,
) => {
  const dataaRef = firestore().collection('usernames');
  setNoMoreData && setNoMoreData(false);

  // If in

  dataaRef // Go to whichever users clicked on data
    .doc(username.toLowerCase())
    .collection(screen) // Go to followers/following
    .orderBy('followedAt')
    .limit(6)
    .get()
    .then((snapshot) => {
      setLoading(true);
      snapshot.empty
        ? null
        : setLastVisible(
            snapshot.docs[snapshot.docs.length - 1].data().followedAt,
          );
      let promises = [];
      // 1b. For each document, return that document data
      snapshot.forEach((doc) => {
        const data = doc.data();
        promises.push(
          data.path.get().then((res) => {
            const userData = res.data();

            // Go to logged in users directory to see
            // if they are following these users in this
            // users following/followers page so we can
            // differentiate whether to display follow/unfollow button
            return dataaRef
              .doc(
                currentuser === undefined
                  ? username.toLowerCase()
                  : currentuser.toLowerCase(),
              )
              .collection('Following')
              .doc(doc.id)
              .get()
              .then((searchedDocs) => {
                return {
                  profileName: doc.id ? doc.id : null,
                  displayName: userData.displayName
                    ? userData.displayName
                    : null,
                  followerCount:
                    userData.followers !== undefined ? userData.followers : 0,
                  followingCount:
                    userData.following !== undefined ? userData.following : 0,
                  imageUrl: userData.imageUrl ? userData.imageUrl : null,
                  isFollowed: searchedDocs.exists ? true : false,
                };
              });
          }),
        );
      });
      // 1c. set All document data to followingData
      Promise.all(promises).then((res) => {
        setfollowingData(res);
        // console.log('res', res);
      });
      setLoading(false);
      setRefresh && setRefresh(false);
    });
};

你实际上不能那样做。 由于从 useEffect 返回的 function 充当清理 function。 您通常会清理您的背部,例如在组件处置时移除事件侦听器等。

useEffect(() => {

  document.addEventListenter('click', () => {});

  function cleanup() {
    document.removeEventListener('click', () => {});
  };

  return cleanup;

})

这就是 useEffect 的工作原理。 因此,在您的情况下,当组件被卸载时,它抱怨 state 更新,这在反应世界中是非法的。

如果您想调用它,只需调用它。

useEffect(() => {
  const setState = () => setStateData(data);
  setState();
}, [data, refresh]);

或者更好的方法是在 useEffect 之外定义您的 function,并在其中调用它。

const setState = () => setStateData(data);

useEffect(() => {
  if (!data) return;
  setState();
}, [data, refresh]);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM