在父 Refresh React Native 上更新子组件数据

Update Child Component Data on Parent Refresh React Native

我是 React Native 的新手,目前正在尝试在我的应用程序中实现下拉刷新功能。这是我的 Parent 组件片段:

function MainScreenBoss({ navigation }) {
    const [refreshing, setRefreshing] = useState(false);

    //here I'm trying to refresh (example from docs)
    const onRefresh = React.useCallback(async () => {
        setRefreshing(true);

        wait(2000).then(setRefreshing(false));
    }, [refreshing]);

    return (
        <ScrollView
            contentContainerStyle={styles.containerScroll}
            refreshControl={
                <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
            }>
            <View style={styles.container}>
                //other components here
                <View style={styles.containerWidget}>
                    //need to refresh this component
                    <Widget style={styles.widget} />
                </View>
            </View>
        </ScrollView>
    );
}

我正在尝试刷新 Widget 组件,因为它在其中调用了 API url 并带有加载动画。这是 Widget 组件的片段:

function Widget() {
    const [isLoading, setLoading] = useState(true);
    const [data, setData] = useState([]);

    //call to api returns data
    useEffect(() => {
        getData(API_GET_WIDGET_DATA, setLoading, setData);
    }, []);

    return (
        <View style={styles.container}>
            {isLoading ? (
                <ActivityIndicator
                    loader="blue"
                    visible={isLoading}
                    style={styles.animation}
                />
            ) : (
                <>
                    <View style={styles.Contents}>
                    //need to refresh data is it used in here when loading is finished
                    </View>
                </>
            )}
        </View>
    );
}

我想我需要强制更新widget组件或以某种方式重新启动加载功能,但我不太明白我该怎么办。

编辑: api 函数如下所示:

export function getData(reqOptions, setLoading, setData) {
    fetch(apiURL, reqOptions)
        .then((response) => response.json())
        .then((json) => setData(json.data))
        .catch((error) => console.error(error))
        .finally(() => setLoading(false));
}

如果我理解得很好,为了更新您的小部件,您必须重新执行 useEffect 中的提取。

您当前的 useEffect 仅在组件挂载时执行,作为 dep。数组为空。从您的父组件的外观来看,Widget 不会被卸载,因此您的 useEffect 只被调用一次。 您需要做的是获取您的 refreshing 状态并将其传递给 Widget,以便它知道何时必须重新获取数据。

尝试这样的事情:

function MainScreenBoss({ navigation }) {
    const [refreshing, setRefreshing] = useState(false);

    //here I'm trying to refresh (example from docs)
    const onRefresh = React.useCallback(async () => {
        setRefreshing(true);

        wait(2000).then(setRefreshing(false));
    }, [refreshing]);

    return (
        <ScrollView
            contentContainerStyle={styles.containerScroll}
            refreshControl={
                <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
            }>
            <View style={styles.container}>
                //other components here
                <View style={styles.containerWidget}>
                    //need to refresh this component
                    <Widget style={styles.widget} refreshing={refreshing} /> // pass this prop
                </View>
            </View>
        </ScrollView>
    );
}

小部件:

function Widget(props) {
    const [isLoading, setLoading] = useState(true);
    const [data, setData] = useState([]);

    //call to api returns data

   useEffect(() => {
        getData(API_GET_WIDGET_DATA, setLoading, setData);
    }, []);

    useEffect(() => {
      if (props.refreshing) {
        getData(API_GET_WIDGET_DATA, setLoading, setData);
      }
    }, [props.refreshing]); // on every refreshing `true` state

    return (
        <View style={styles.container}>
            {isLoading ? (
                <ActivityIndicator
                    loader="blue"
                    visible={isLoading}
                    style={styles.animation}
                />
            ) : (
                <>
                    <View style={styles.Contents}>
                    //need to refresh data is it used in here when loading is finished
                    </View>
                </>
            )}
        </View>
    );
}

编辑: 您可以修改现有的 useEffect 以包括 data 的检查,或者创建另一个仅在挂载时运行,另一个 useEffect 运行 在更新状态上运行。我添加了第二种情况。

编辑 2:

  1. 这没什么不对,实际上这样更好,因为刷新是在正确的时间处理的,当调用完成并且数据完成时。使用您当前的配置,调用可能未完成,但在 2 秒后您将刷新设置为 false,这可能会带来问题。

  2. hooks 的美妙之处在于,与 hooks 引入之前 React 的 class 方法相比,你可以使用任意数量的 hooks。所以这没有问题,但你实际上可以改变它并得到类似的东西:

    useEffect(() => {
      if (!data || props.refreshing) {
        getData(API_GET_WIDGET_DATA, setLoading, setData);
      }
    }, [data, props.refreshing]);
    
  3. 如果可以的话,最后一件事:我不会将状态设置器传递给你的 fetch fn,我会处理组件中的状态更新并确保 fn returns你的数据。这只是为了关注点分离的原因。