反应本机导航-添加/更新/删除项目时屏幕上的更新列表

时间:2020-07-31 23:52:50

标签: reactjs react-native react-native-navigation

我正在使用React Native构建移动应用程序。我正在使用react-native-navigation库中的堆栈导航器。

堆栈有两个屏幕,第一个屏幕ItemsListScreen显示带有添加按钮的项目列表,单击添加按钮导航到第二个屏幕AddItemScreen,该屏幕显示带有保存内容的项目的一些输入按钮。单击保存按钮将导航回到列表屏幕。

项目当前保存在本地SQLite数据库中,但将来将保存在服务器上。

ItemsListScreen.js

import React, { useEffect, useState, useContext } from "react";
import { Button, Image, Platform, StyleSheet, View, TouchableOpacity } from "react-native";
import { ScrollView } from "react-native-gesture-handler";
import { Ionicons } from "@expo/vector-icons";

import DatabaseContext from "../db/DatabaseContext";

export default function ItemsListScreen({ navigation }) {
    const db = useContext(DatabaseContext);

    const [items, setItems] = useState([]);

    useEffect(() => {
        navigation.setOptions({
            headerRight: () => {
                return (
                    <TouchableOpacity activeOpacity={0.5} style={{ paddingRight: 10 }} onPress={() => navigation.navigate("AddItem")}>
                        <Ionicons name="md-add" size={30} />
                    </TouchableOpacity>
                );
            },
        });

        db.getItems().then((data) => {
            setItems(data);
        });
    }, []);

    return (
        <View style={styles.container}>
            <ScrollView style={styles.container} contentContainerStyle={styles.contentContainer}>
                {items.map((item, index) => (
                    <View key={index} style={styles.item}>
                        <Text style={styles.subSection}>{item.title}</Text>
                    </View>
                ))}
            </ScrollView>
        </View>
    );
}

AddItemScreen.js

import React, { useState, useEffect, useContext } from "react";
import { StyleSheet, View, Dimensions, TextInput, ScrollView, TouchableOpacity, Picker, Switch } from "react-native";
import DateTimePicker from "@react-native-community/datetimepicker";
import { Ionicons } from "@expo/vector-icons";

import DatabaseContext from "../db/DatabaseContext";

export default function AddItemScreen({ navigation }) {
    const db = useContext(DatabaseContext);

    const [item, setItem] = useState({
        title: "",
        description: "",
        // more properties
    });

    const saveItem = () => {
        db.saveItem(item);
        navigation.navigate("ItemsList");
    };

    useEffect(() => {
        navigation.setOptions({
            headerRight: () => {
                return (
                    <TouchableOpacity activeOpacity={0.5} style={{ paddingRight: 10 }} onPress={saveItem}>
                        <Ionicons name="md-save" size={30} />
                    </TouchableOpacity>
                );
            },
        });
    }, [item]);
    
    return (
        <View style={styles.scene}>
            <ScrollView>
                <Text style={styles.label}>Title</Text>
                <TextInput style={styles.field} value={item.title} onChangeText={(text) => setItem((prevState) => ({ ...prevState, title: text }))} />

                <Text style={styles.label}>Description</Text>
                <TextInput style={styles.field} value={item.description} onChangeText={(text) => setItem((prevState) => ({ ...prevState, description: text }))} />          
                
                {/* more inputes */}
            </ScrollView>
        </View>
    );
}

我的问题是,添加新项目时,ItemsListScreen上的列表未更新。我需要重新加载应用程序才能更新列表。

我试图从ItemsListScreen中的useEffect中删除第二个参数(空数组),它可以工作,但是我认为这是一个不好的解决方案,因为它每次重新渲染时都会不断从db中读取数据。

每当用户导航回列表屏幕时,如何刷新列表?我以为useEffect会在屏幕激活时执行,但似乎不会。

1 个答案:

答案 0 :(得分:1)

您将通过将导航焦点侦听器添加到ItemsListScreen.js来解决。以此方式替换您的useEffet

useEffect(() => {
        navigation.setOptions({
            headerRight: () => {
                return (
                    <TouchableOpacity activeOpacity={0.5} style={{ paddingRight: 10 }} onPress={() => navigation.navigate("AddItem")}>
                        <Ionicons name="md-add" size={30} />
                    </TouchableOpacity>
                );
            },
        });

        const unsubscribe = navigation.addListener('focus', () => {
             db.getItems().then((data) => {
                setItems(data);
             });
        });

        return unsubscribe;

        
    }, []);