简体   繁体   English

为什么我的 useState 值会在 onPress 方法中重置?

[英]Why does my useState value reset in onPress method?

I'm using a useState called tripState in my react native component.我在我的本机反应组件中使用了一个名为 tripState 的 useState。

const [tripState, setTripState] = useState<NewTripState>({
    name: "",
    description: "",
    thumbnail: "",
});

I change its value in text field using function:我使用 function 在文本字段中更改其值:

const onChange = (
    key: keyof NewTripState,
    value: string | null,
): void => {
    setTripState({
        ...tripState,
        [key]: value,
    });
};

Text input:文字输入:

<TextInput
    value={tripState.name}
    onChangeText={(value: string): void => {
        onChange("name", value);
    }}
    placeholder={"Enter trip name"}
/>

which is called on text inputs.在文本输入时调用。 If I console.log the value in:如果我 console.log 中的值:

useEffect(() => {
    console.log(tripState); // console.logs updated state
}, [tripState]);

it console logs correct (updated) value, but the moment i try to console log it in my onSubmit method which is called on onPress on Pressable , I get the initial value.它控制台记录正确的(更新的)值,但是当我尝试在我的onSubmit方法中控制台记录它时,该方法在Pressable上的onPress上调用,我得到了初始值。

<Pressable onPress={onSubmit}>
    <Text>Save</Text>
</Pressable>
const onSubmit = () => {
    console.log(tripState); // console.logs initial state
};

Can someone please help me?有人可以帮帮我吗? I don't know that to do anymore.我不知道该怎么做了。

Edit 1: Entire component:编辑 1:整个组件:

import React, { useEffect, useState } from "react";
import { useColorScheme } from "react-native";
import { getUserHoliday } from "../../api/firestore/trips";
import ProfilePicture from "../../components/ProfilePicture";
import {
    View,
    Text,
    Pressable,
} from "../../components/Themed";
import { tintColorLight } from "../../constants/Colors";
import store from "../../redux/store";
import { getUserId } from "../../redux/stores/user";
import { Holiday } from "../../utils/types/holiday";
import { Trip } from "../../utils/types/trip";

type NewTripScreenProps = {
    navigation: any;
    route: any;
};

export type NewTripState = {
    name: string;
    description: string;
    thumbnail: string;
};

const NewTripScreen = (props: NewTripScreenProps) => {
    const { navigation } = props;

    const [tripState, setTripState] = useState<NewTripState>({
        name: "",
        description: "",
        thumbnail: "",
    });

    useEffect(() => {
        console.log(tripState);
    }, [tripState]);

    const onChange = (
        key: keyof NewTripState,
        value: string | null,
    ): void => {
        setTripState((currentValue) => ({
            ...currentValue,
            [key]: value,
        }));
    };

    const userId = getUserId(store.getState());

    const colorScheme = useColorScheme();

    useEffect(() => {
        getUserHoliday(userId).then((holidays) => {
            setHolidays(holidays);
        });

        navigation.setOptions({
            headerTitle: "New Trip",
            headerRight: () => (
                <Pressable onPress={onSubmit}>
                    <Text
                        style={{
                            color: tintColorLight,
                            fontSize: 18,
                        }}
                    >
                        Save
                    </Text>
                </Pressable>
            ),
            headerTintColor: tintColorLight,
            headerTitleStyle: {
                color: colorScheme === "dark" ? "#fff" : "#000",
            },
        });
    }, []);

    const onSubmit = () => {
        console.log(tripState.name);

        const trip: Trip & { holiday?: Holiday | null } = {
            userId: userId,
            ...tripState,
            status: "created",
        };
    };

    return (
            <View>
                <Text
                    style={{
                        fontWeight: "bold",
                        fontSize: 32,
                        padding: 10,
                    }}
                >
                    New Trip
                </Text>
                <View style={{ alignItems: "center", marginTop: 20 }}>
                    <TextInput
                        value={tripState.name}
                        onChangeText={(value: string): void => {
                            onChange("name", value);
                        }}
                        placeholder={"Enter trip name"}
                    />

                    <TextInput
                        value={tripState.description}
                        onChangeText={(value: string): void => {
                            onChange("description", value);
                        }}
                        placeholder={"Enter Description"}
                        style={{ marginTop: 20 }}
                    />
                    <Text
                        style={{
                            fontWeight: "bold",
                            fontSize: 32,
                            padding: 10,
                        }}
                    >
                        Thumbnail
                    </Text>
                    <ProfilePicture
                        photoURL={tripState.thumbnail}
                        onPress={() => {}}
                    />
                </View>
            </View>
    );
};

export default NewTripScreen;

It is happening because of useEffect with empty dependency array.这是因为 useEffect 和空依赖数组而发生的。 When you add onSubmit() on Pressable's onPress listener, because of useEffect with empty dependency array the original value of tripState inside onSubmit is used.当您在 Pressable 的 onPress 侦听器上添加onSubmit()时,由于 useEffect 具有空依赖数组,因此使用onSubmit内的 tripState 的原始值。

Change the code like this像这样更改代码

    useEffect(() => {
        getUserHoliday(userId).then((holidays) => {
            setHolidays(holidays);
        });

        navigation.setOptions({
            headerTitle: "New Trip",
            headerTintColor: tintColorLight,
            headerTitleStyle: {
                color: colorScheme === "dark" ? "#fff" : "#000",
            },
        });
    }, []);

  useEffect(() => {
       navigation.setOptions({
           headerRight: () => (
                <Pressable onPress={onSubmit}>
                    <Text
                        style={{
                            color: tintColorLight,
                            fontSize: 18,
                        }}
                    >
                        Save
                    </Text>
                </Pressable>
            )
           });
    }, [tripState]);


The topic you're looking for is called 'stale values'.您要查找的主题称为“过时值”。 It's what happens when values get locked in to your function, and don't refresh.当值被锁定到您的 function 并且不刷新时,就会发生这种情况。 React useState has a way of solving this, really simply: React useState 有办法解决这个问题,非常简单:

Instead of:代替:

setTripState({
  ...tripState,
  [key]: value,
});

Tell the setState that you want to use the most up-to-date value:告诉 setState 你想使用最新的值:

setTripState(currentValue => ({
  ...currentValue,
  [key]: value,
}));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM