如何在本机反应中使用后退按钮重新渲染组件?

roc*_*one 9 javascript reactjs react-native redux

如果我从主屏幕转到产品详细信息屏幕,然后转到购物车屏幕,则状态更新工作正常,但如果从购物车屏幕添加商品或删除商品,然后导航回产品详细信息或主屏幕,则状态不会更新,为什么会这样?请参阅下面的 vudeo 链接:https://drive.google.com/file/d/1AjrFMAXBs9Gzc5Onbm1uf-eW9gFfHxMU/view ?usp=sharing

我正在使用 redux,但即使 redux 存储状态已更新,它仍然不会渲染具有更新状态的组件,为什么会这样?

我正在考虑使用反应导航事件,但我收到错误,为什么会这样?如何解决问题?这是 redux 问题还是 React 导航问题?当导航回上一屏幕时,组件是否会重新渲染?

如果我刷新模拟器屏幕,状态就会更新并正确显示,为什么会发生这种情况?

我想在焦点返回时重新渲染 Home 组件,但出现错误。为什么这样?

截屏:

在此输入图像描述

代码:

home.js:

import React, {useState, useEffect} from 'react';
import {
    StyleSheet,
    ScrollView,
    View,
    Text,
    StatusBar,
    Image,
    TouchableOpacity,
    Button
} from 'react-native';
import Product from '../product/product';
import { useFocusEffect } from '@react-navigation/native';
import axios from 'axios';

export const Home = (props) => {

    const [categories, setCategories] = useState([]);

    useFocusEffect(
        React.useCallback(() => {
            const unsubscribe = FetchCategoryData();

            return () => unsubscribe();
        }, [])
    );

    const FetchCategoryData = () => {

        axios.get(`http://localhost:5000/api/categories`)
            .then(res => {
                console.log("All categories: ", res.data.data);

                setCategories([...res.data.data]);

                console.log("useeffect categories",categories)
            })
            .catch(error => console.log("Error: ", error))
    }

    return(
        <ScrollView style={styles.root}>
            <View style={{marginTop: 15, marginLeft: 15, marginBottom: 15}}> 
                <ScrollView horizontal={true} style={styles.container}>
                    <TouchableOpacity>
                        <View style={{marginRight: 15}}>
                            <Image source={require('../../assets/img/fruits.jpg')} style={{width: 325, height: 200, borderRadius: 10}}/>
                        </View>
                    </TouchableOpacity>
                    <TouchableOpacity>
                        <View style={{marginRight: 15}}>
                            <Image source={require('../../assets/img/grocery.jpg')} style={{width: 325, height: 200, borderRadius: 10}}/>
                        </View>
                    </TouchableOpacity>
                    <TouchableOpacity>
                        <View style={{marginRight: 15}}>
                            <Image source={require('../../assets/img/fruits.jpg')} style={{width: 325, height: 200, borderRadius: 10}}/>
                        </View>
                    </TouchableOpacity>
                </ScrollView>
            </View>
            {categories && categories.length > 0 ? categories.map(val => <CategoryList key={val._id} category={val.name} navigation={props.navigation}/>) : null}
        </ScrollView>
    )
}
Run Code Online (Sandbox Code Playgroud)

aur*_*lia 14

查看reactnavigation.org/docs/function-after-focusing-screen

简而言之,使用

const isFocused = useIsFocused();
Run Code Online (Sandbox Code Playgroud)

每次窗口聚焦或未聚焦时,组件中的某个位置都会强制重新渲染。

当我们聚焦和取消聚焦屏幕时,useIsFocused 挂钩将导致我们的组件重新渲染。当屏幕进入和离开焦点时,使用此钩子组件可能会导致不必要的组件重新渲染。这可能会导致问题,具体取决于我们呼吁关注的操作类型。因此,我们建议仅在需要触发重新渲染时才使用此钩子。对于订阅事件或获取数据等副作用,请使用上述方法。


eme*_*nto 3

返回时,React Navigation 不会重新渲染屏幕。这样您的屏幕就不必在每次导航时重新获取数据或显示加载指示器。如果您想在屏幕出现时执行一些更新,请尝试阅读此内容

简而言之,React Navigation 允许您订阅导航事件,例如屏幕刚刚获得焦点时:


export default class Screen extends Component {

    navigationSubscription;

    componentDidMount() {
        // Fetch initial data and add navigation listener
        // ...

        this.navigationSubscription = this.props.navigation.addListener('didFocus', this.onFocus);
    }

    componentWillUnmount() {
        this.navigationSubscription.remove();
    }

    // This function will be called everytime this screen is shown
    onFocus = (payload) => {
        console.log(payload);
        // You can then check for updates here
    }

    render() {
        return (
            <Text>I'm a screen</Text>
        );
    }
}
Run Code Online (Sandbox Code Playgroud)