React Context не обновляет данные

Я создал React Context API, в нем я сохранил такую ​​информацию, как имя, хобби, дату рождения и т. д. Я создал состояние в файле контекста и функцию, которая меняет состояние при вызове. Я использую контекст в SignUpForm1.js и SignUpForm2.js, я пытаюсь обновить состояние переменных контекста при изменении текстового поля, но данные в контексте не обновляются.

UserData.js (контекст)

import React from "react";
import { useState } from "react";
import {Text} from 'react-native';
import { createContext } from "react";


const SignUpContext = React.createContext({});

const UserData = (props)=>{

  var state = {
    pref_pronoun: "",
    DOB: "",
    course: "",
    first_name: "",
    hobby_1: "",
    hobby_2: "",
    hobby_3: "",
    hobby_4: "",
    hobby_5: "",
    home_city: "",
    last_name: "",
    nationality: "",
    student_email: "",
    university: "",
  }

  const [userDetails , setDetails] = useState(state);

  const updateFormData = (field, value) => {
    setDetails({ [field]: value });
    console.info(state);
  };

  return (
    <SignUpContext.Provider value = {{state, updateFormData}}>
      {props.children}
    </SignUpContext.Provider>
  )

}

export {SignUpContext, UserData} ;

SignUpForm1.js


import {
  Image,
  Text,
  StyleSheet,
  View,
  StatusBar,
  ScrollView,
  RefreshControl,
} from "react-native";
import DropDown from "./DropDown";
import Input from "./Input";
import {
  KeyboardAvoidingView,
  TouchableWithoutFeedback,
  Keyboard,
} from "react-native";
import { useCallback, useContext, useState } from "react";
import CustomButton from "./CustomButton";
import { useNavigation } from "@react-navigation/native";
import DateTimePickerModal from "react-native-modal-datetime-picker";
import { Button } from "react-native";
import { SignUpContext, UserData } from "./GlobalUtil/UserData";

const HideKeyboard = ({ children }) => (
  <TouchableWithoutFeedback onPress = {() => Keyboard.dismiss()}>
    {children}
  </TouchableWithoutFeedback>
);

function SignUpForm1() {
  

  const [isDatePickerVisible, setDatePickerVisibility] = useState(false);
  const s_context = useContext(SignUpContext);

  const showDatePicker = () => {
    setDatePickerVisibility(true);
  };

  const hideDatePicker = () => {
    setDatePickerVisibility(false);
  };


  const navigation = useNavigation();
  const NationalityData = ["Football", "Cricket", "Programmming", "Coding"];
  const [refreshing, setRefreshing] = useState(false);

  const onRefresh = useCallback(() => {
    setRefreshing(true);
    setTimeout(() => {
      setRefreshing(false);
    }, 2000);
  }, []);
  const statusBarHeight = Platform.OS === "ios" ? 50 : StatusBar.currentHeight;

  return (

        <KeyboardAvoidingView behavior = "padding">
          <HideKeyboard>
            <View
              style = {{
                height: "100%",
                width: "100%",
                backgroundColor: "#f1be63",
              }}
            >
              <View
                style = {{ backgroundColor: "#f1be63", height: statusBarHeight }}
              >
                <StatusBar barStyle = "dark-content" />
              </View>
              <ScrollView
                contentContainerStyle = {styles.rootContainer}
                refreshControl = {
                  <RefreshControl
                    refreshing = {refreshing}
                    onRefresh = {onRefresh}
                  />
                }
              >
                <Image
                  source = {require("../assets/aeroplane.png")}
                  style = {styles.image}
                  resizeMode = "contain"
                />
                <Text style = {styles.header}>Let's get you set up</Text>
                <Text style = {styles.lowerHeader}>
                  (we promise that it won't take long)
                </Text>

                <View style = {[styles.textFieldsContainer]}>
                  <View style = {{ alignItems: "center" }}>
                    <Input
                      isLabel = {true}
                      label = "Preferred Pronoun"
                      placeholder = "He/Him"
                      onChangeText = {(text) => {
                        s_context.updateFormData("pref_pronoun", text);
                      }}
                    />
                    <Input
                      isLabel = {true}
                      label = "First Name"
                      placeholder = "Cameron"
                      onChangeText = {(text) => {
                        s_context.updateFormData("first_name", text);
                      }}
                    />
                    <Input
                      isLabel = {true}
                      label = "Last Name"
                      placeholder = "Cox"
                      onChangeText = {(text) => {
                        s_context.updateFormData("last_name", text);
                      }}
                    />
                    <View
                      style = {{
                        backgroundColor: "white",
                        width: "80%",
                        borderRadius: 5,
                        marginTop: 10,
                      }}
                    >
                      <Button
                        title = "Date of Birth"
                        onPress = {showDatePicker}
                        color = "gray"
                      />
                    </View>
                    <DateTimePickerModal
                      isVisible = {isDatePickerVisible}
                      mode = "date"
                      onConfirm = {(date) => {
                        s_context.updateFormData('dob', date);
                        hideDatePicker();
                      }}
                      onCancel = {hideDatePicker}
                      buttonTextColorIOS = "white"
                      pickerContainerStyleIOS = {{ backgroundColor: "#D89D35" }}
                      isDarkModeEnabled
                    />
                  </View>

                  <View style = {{ alignItems: "center" }}>
                    <DropDown
                      data = {NationalityData}
                      placeholder = "Nationality"
                      onSelect = {(selectedItem, index) => {
                        s_context.updateFormData("nationality", selectedItem);
                        }}
                    />
                    <DropDown
                      data = {NationalityData}
                      placeholder = "University"
                      onSelect = {(selectedItem, index) => {
                        s_context.updateFormData("university", selectedItem);
                        }}
                    />
                    <DropDown
                      data = {NationalityData}
                      placeholder = "Course"
                      onSelect = {(selectedItem, index) => {
                        s_context.updateFormData("course", selectedItem);
                        }}
                    />
                    <DropDown
                      data = {NationalityData}
                      placeholder = "HomeTown City"
                      onSelect = {(selectedItem, index) => {
                        s_context.updateFormData("homeCity", selectedItem);
                        }}
                    />
                    <CustomButton
                      isBorder = {true}
                      title = "Next"
                      onPress = {() => {
                        navigation.navigate("SignUp2");
                      }}
                    />
                  </View>
                </View>
              </ScrollView>
            </View>
          </HideKeyboard>
        </KeyboardAvoidingView>
  );
}

const styles = StyleSheet.create({
  rootContainer: {
    height: "125%",
    justifyContent: "flex-start",
    alignItems: "center",
    marginTop: 24,
  },
  textFieldsContainer: {
    width: "100%",
    flex: 1,
  },
  image: {
    width: "25%",
    height: "10%",
    marginTop: 24,
  },
  header: {
    color: "white",
    fontSize: 26,
    fontWeight: "bold",
    marginVertical: 6,
  },
  lowerHeader: {
    color: "white",
    fontSize: 12,
    marginBottom: 24,
  },
});
export default SignUpForm1;

SignUpForm2.js


import {
  View,
  Text,
  TouchableWithoutFeedback,
  StyleSheet,
  StatusBar,
  ScrollView,
} from "react-native";

import { KeyboardAvoidingView } from "react-native";
import { Avatar } from "react-native-elements";
import Input from "./Input";
import DropDown from "./DropDown";
import { Keyboard } from "react-native";
import { Platform } from "react-native";
import { useNavigation } from "@react-navigation/native";
import CustomButton from "./CustomButton";
import { useState, useContext } from "react";
import { createNewUser } from "./util/auth";
import { SignUpContext, UserData } from "./GlobalUtil/UserData";

const HideKeyboard = ({ children }) => (
  <TouchableWithoutFeedback onPress = {() => Keyboard.dismiss()}>
    {children}
  </TouchableWithoutFeedback>
);

function SignUpForm2() {

  const s_context = useContext(SignUpContext);


  async function FinishBtnHandler()
   {
    console.info("Creating New User");
    console.info("Email: " + emailText.trim());
    console.info("Password: " + passwordText.trim());
    await createNewUser(emailText.trim(), passwordText.trim());

  }

  const navigation = useNavigation();
  const hobbiesData = ["Football", "Cricket", "Programmming", "Coding"];

  const [emailText, setEmailText] = useState("");
  function handleEmailText(newText) {
    console.info("Email: " + newText);
    setEmailText(newText);
  }
  const [passwordText, setPasswordText] = useState("");
  function handlePasswordText(newText) {
    console.info("Password: " + newText);
    setPasswordText(newText);
  }

  function avatarPressHandler() {
    console.info("Pressed!");
  }
  const statusBarHeight = Platform.OS === "ios" ? 50 : StatusBar.currentHeight;
  return (
        <KeyboardAvoidingView behavior = "padding" style = {{ flex: 1 }}>
          <HideKeyboard>
            <ScrollView>
              <View
                style = {{
                  position: "absolute",
                  top: 0,
                  left: 0,
                  right: 0,
                  zIndex: 999,
                }}
              >
                <View
                  style = {{
                    backgroundColor: "#f1be63",
                    height: statusBarHeight,
                  }}
                >
                  <StatusBar barStyle = "dark-content" />
                </View>
              </View>
              <View style = {[styles.rootContainer, { paddingBottom: 48 }]}>
                <View style = {styles.lowerContainer}>
                  <Text style = {styles.primaryText}>You're almost there!</Text>
                  <Avatar
                    rounded
                    size = {170}
                    containerStyle = {{ alignSelf: "center", marginTop: 24 }}
                    //icon = {{ name: "user", type: "font-awesome" }}
                    overlayContainerStyle = {{ backgroundColor: "#f1be63" }}
                    source = {{
                      uri: "https://cdn.pixabay.com/photo/2019/11/03/20/11/portrait-4599553__340.jpg",
                    }}
                  >
                    <Avatar.Accessory size = {20} onPress = {avatarPressHandler} />
                  </Avatar>
                  <Text
                    style = {[
                      styles.secondaryText,
                      { marginBottom: 8, marginTop: 16 },
                    ]}
                  >
                    Express yourself & customize your avatar
                  </Text>
                  <Input
                    isLabel = {true}
                    label = "Student Email"
                    placeholder = "cce22rnu@uea.ac.uk"
                    onChangeText = {handleEmailText}
                    defaultValue = {emailText}
                  />
                  <Input
                    isLabel = {true}
                    label = "Create Password"
                    placeholder = "iLoveyoushakila123"
                    onChangeText = {handlePasswordText}
                    defaultValue = {passwordText}
                  />
                  <Input
                    isLabel = {true}
                    label = "Confirm Password"
                    placeholder = "iLoveyoushakila123"
                  />

                  <Text style = {styles.secondaryText}>
                    Now the exciting part - select your top 5 hobbies
                  </Text>

                  <View style = {{ alignItems: "center", marginTop: 16 }}>
                    <DropDown
                      data = {hobbiesData}
                      onSelect = {(selectedItem, index) => {
                        s_context.updateFormData("hobby_1", selectedItem);
                      }}
                    />
                    <DropDown data = {hobbiesData} onSelect = {(selectedItem, index) => {
                        s_context.updateFormData("hobby_2", selectedItem);
                      }}/>
                    <DropDown data = {hobbiesData} onSelect = {(selectedItem, index) => {
                        s_context.updateFormData("hobby_3", selectedItem);
                      }}/>
                    <DropDown data = {hobbiesData} onSelect = {(selectedItem, index) => {
                        s_context.updateFormData("hobby_4", selectedItem);
                      }}/>
                    <DropDown data = {hobbiesData} onSelect = {(selectedItem, index) => {
                        s_context.updateFormData("hobby_5", selectedItem);
                      }}/>

                    <CustomButton
                      isBorder = {true}
                      title = "Finish"
                      /*onPress = {()=>{navigation.navigate("ConfirmId")}}*/ onPress = {
                        FinishBtnHandler
                      }
                    />
                  </View>
                </View>
              </View>
            </ScrollView>
          </HideKeyboard>
        </KeyboardAvoidingView>
  );
}

const styles = StyleSheet.create({
  rootContainer: {
    flex: 1,
    justifyContent: "flex-start",
    alignItems: "center",
    backgroundColor: "#f1be63",
    marginTop: 48,
    backgroundColor: "#f1be63",
  },
  lowerContainer: {
    flex: 1,
    width: "100%",
    alignItems: "center",
  },
  primaryText: {
    color: "white",
    fontSize: 24,
    fontWeight: "bold",
  },
  secondaryText: {
    marginTop: 8,
    color: "white",
    fontSize: 12,
    fontWeight: "bold",
  },
});

export default SignUpForm2;

Компоненты, потребляющие контекст, обертываются поставщиком контекста?

ivanatias 13.02.2023 23:40

Где вы вообще используете значение состояния контекста?

Phil 13.02.2023 23:51
Руководство для начинающих по веб-разработке на React.js
Руководство для начинающих по веб-разработке на React.js
Веб-разработка - это захватывающая и постоянно меняющаяся область, которая постоянно развивается благодаря новым технологиям и тенденциям. Одним из...
Калькулятор CGPA 12 для семестра
Калькулятор CGPA 12 для семестра
Чтобы запустить этот код и рассчитать CGPA, необходимо сохранить код как HTML-файл, а затем открыть его в веб-браузере. Для этого выполните следующие...
Как собрать/развернуть часть вашего приложения Angular
Как собрать/развернуть часть вашего приложения Angular
Вам когда-нибудь требовалось собрать/развернуть только часть вашего приложения Angular или, возможно, скрыть некоторые маршруты в определенных средах?
Оптимизация React Context шаг за шагом в 4 примерах
Оптимизация React Context шаг за шагом в 4 примерах
При использовании компонентов React в сочетании с Context вы можете оптимизировать рендеринг, обернув ваш компонент React в React.memo сразу после...
Интервьюер: Почему &apos;[] instanceof Object&apos; возвращает &quot;true&quot;?
Интервьюер: Почему '[] instanceof Object' возвращает "true"?
Все мы знаем, что [] instanceof Array возвращает true, но почему [] instanceof Object тоже возвращает true?
Абстрактное синтаксическое дерево (AST) и как оно работает с ReactJS
Абстрактное синтаксическое дерево (AST) и как оно работает с ReactJS
Абстрактное синтаксическое дерево (AST) - это древовидная структура данных, которая представляет структуру и иерархию исходного кода на языке...
0
2
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам нужно передать переменную состояния userDetails в контекст, а не начальное значение state

<SignUpContext.Provider value = {{ state: userDetails, updateFormData }}>
  {props.children}
</SignUpContext.Provider>

Передача объекта начального состояния не увидит никаких сделанных вами обновлений.

Кроме того, вы должны использовать формат функциональных обновлений для динамической установки свойств в вашем состоянии.

setDetails((prev) => ({ ...prev, [field]: value }));

Наконец, логирование состояния консоли — бессмысленное занятие, которое часто дает неожиданные результаты. Просто не делай этого

Другие вопросы по теме