Я создал 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;
Где вы вообще используете значение состояния контекста?
Вам нужно передать переменную состояния userDetails в контекст, а не начальное значение state
<SignUpContext.Provider value = {{ state: userDetails, updateFormData }}>
{props.children}
</SignUpContext.Provider>
Передача объекта начального состояния не увидит никаких сделанных вами обновлений.
Кроме того, вы должны использовать формат функциональных обновлений для динамической установки свойств в вашем состоянии.
setDetails((prev) => ({ ...prev, [field]: value }));
Наконец, логирование состояния консоли — бессмысленное занятие, которое часто дает неожиданные результаты. Просто не делай этого
Компоненты, потребляющие контекст, обертываются поставщиком контекста?