簡體   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