异步redux调度导致内存泄漏

时间:2020-07-29 21:19:37

标签: reactjs react-native react-redux

当我单击导航以获取完整内容时,我面临以下警告。我该如何解决这个问题

警告:无法在已卸载的组件上执行React状态更新。这是空操作,但表示内存泄漏 你的申请。要修复,取消使用useEffect清理功能的%s。%s中的所有订阅和异步任务

const SearchResultScreen = ({ navigation, route }) => {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  const [modalVisible, setModalVisible] = useState(false);
  const [selectedValue, setSelectedValue] = useState("lastHour");

  const dispatch = useDispatch();
  const newsies = useSelector((state) => state.searchResult.newsies);

  const fetchData = useCallback(async () => {
    setLoading(true);
    try {
      await dispatch(getSearchResults());
      setError(null);
    } catch (e) {
      setError("Something went wrong!");
    }
    setLoading(false);
  }, []);

  useEffect(() => {
    fetchData();
  }, [fetchData]);

  useLayoutEffect(() => {
    navigation.setOptions({
      headerTitle: () => (
        <TouchableWithoutFeedback onPress={() => navigation.replace("Search")}>
          <Text numberOfLines={1} style={styles.searchBtnText}>
            {route.params ? route.params.itemValue : ""}
          </Text>
        </TouchableWithoutFeedback>
      ),
      headerRight: () => (
        <HeaderButtons>
          <HeaderButton
            iconName="sliders"
            onPressed={() => {
              setModalVisible(true);
            }}
            style={{
              transform: [{ rotate: "-90deg" }],
              backgroundColor: "transparent",
            }}
          />
        </HeaderButtons>
      ),
    });
  }, [navigation, route]);

  if (loading) {
    return <CenteredSpinner />;
  }
  if (!loading && error) {
    return <CenteredErrorBox errorMsg={error} onPressed={fetchData} />;
  }
  if (!loading && newsies.length === 0) {
    return <CenteredErrorBox errorMsg={"No Data Found!"} />;
  }
  return (
    <>
      <CustomModal
        onClosed={() => setModalVisible(false)}
        modalVisible={modalVisible}
      >
        <Text style={styles.CustomModalTitle}>Search Filter</Text>
        <View style={styles.CustomModalBody}>
          <View style={styles.CustomModalBodyFilter}>
            <Text style={styles.CustomModalBodyFilterText}>Published at</Text>
            <CustomPicker
              items={[
                ["Last hour", "lastHour"],
                ["Last Day", "lastDay"],
                ["Last Week", "lastWeek"],
              ]}
              selectedValue={selectedValue}
              onValueChanged={(itemValue) => setSelectedValue(itemValue)}
            />
          </View>
        </View>
        <View style={styles.CustomModalActions}>
          <RippleButton
            style={{ marginRight: 10 }}
            onPressed={() => {
              setModalVisible(false);
            }}
          >
            <Text style={styles.CustomModalActionsBtn}>CANCEL</Text>
          </RippleButton>
          <RippleButton onPressed={() => {}}>
            <Text style={styles.CustomModalActionsBtn}>APPLY</Text>
          </RippleButton>
        </View>
      </CustomModal>
      <FlatList
        initialNumToRender={10}
        showsVerticalScrollIndicator={!Platform.OS === "android"}
        style={styles.list}
        renderItem={({ item }) => (
          <NewsBox
            news={item}
            onPressed={() => navigation.navigate("NewsDetail")}
          />
        )}
        data={newsies}
      />
    </>
  );
};

1 个答案:

答案 0 :(得分:0)

useEffect挂钩可能返回该函数,该组件将在卸载组件以清理异步任务和订阅时被调用一次。

useEffect(()=>{
  // do some usefull staff here, for example subscribing or fetching data:
  ...
  // return cleaning function which will cancel subscribes and uncompleted fetches:
  return () => {
    ...
  }

}, [])

要取消获取或任何其他异步操作,可以尝试AbortController。