React Context is not updating Data.

huangapple go评论71阅读模式
英文:

React Context is not updating Data

问题

以下是您要翻译的内容:

I have created a React Context API, I have stored information such as first_name, hobbies, DOB etc in it. I have created a state in the context file and a function that changes the state when called. I am using the context in SignUpForm1.js and SignUpForm2.js, I am trying to update the state of context variables whenever there is a change in the text field, but the data in the context is not updating.

UserData.js (Context)
```javascript
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.log(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", "Programming", "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;
英文:

I have created a React Context API, I have stored information such as first_name, hobbies, DOB etc in it. I have crated a state in the context file and a function that changes the state when called. I am using the context in SignUpForm1.js and SignUpForm2.js, I am trying to update the state of context variables when ever there is a change in the text field, but the data in the context is not updating.

UserData.js (Context)

import React from &quot;react&quot;;
import { useState } from &quot;react&quot;;
import {Text} from &#39;react-native&#39;;
import { createContext } from &quot;react&quot;;
const SignUpContext = React.createContext({});
const UserData = (props)=&gt;{
var state = {
pref_pronoun: &quot;&quot;,
DOB: &quot;&quot;,
course: &quot;&quot;,
first_name: &quot;&quot;,
hobby_1: &quot;&quot;,
hobby_2: &quot;&quot;,
hobby_3: &quot;&quot;,
hobby_4: &quot;&quot;,
hobby_5: &quot;&quot;,
home_city: &quot;&quot;,
last_name: &quot;&quot;,
nationality: &quot;&quot;,
student_email: &quot;&quot;,
university: &quot;&quot;,
}
const [userDetails , setDetails] = useState(state);
const updateFormData = (field, value) =&gt; {
setDetails({ [field]: value });
console.log(state);
};
return (
&lt;SignUpContext.Provider value = {{state, updateFormData}}&gt;
{props.children}
&lt;/SignUpContext.Provider&gt;
)
}
export {SignUpContext, UserData} ;

SignUpForm1.js


import {
Image,
Text,
StyleSheet,
View,
StatusBar,
ScrollView,
RefreshControl,
} from &quot;react-native&quot;;
import DropDown from &quot;./DropDown&quot;;
import Input from &quot;./Input&quot;;
import {
KeyboardAvoidingView,
TouchableWithoutFeedback,
Keyboard,
} from &quot;react-native&quot;;
import { useCallback, useContext, useState } from &quot;react&quot;;
import CustomButton from &quot;./CustomButton&quot;;
import { useNavigation } from &quot;@react-navigation/native&quot;;
import DateTimePickerModal from &quot;react-native-modal-datetime-picker&quot;;
import { Button } from &quot;react-native&quot;;
import { SignUpContext, UserData } from &quot;./GlobalUtil/UserData&quot;;
const HideKeyboard = ({ children }) =&gt; (
&lt;TouchableWithoutFeedback onPress={() =&gt; Keyboard.dismiss()}&gt;
{children}
&lt;/TouchableWithoutFeedback&gt;
);
function SignUpForm1() {
const [isDatePickerVisible, setDatePickerVisibility] = useState(false);
const s_context = useContext(SignUpContext);
const showDatePicker = () =&gt; {
setDatePickerVisibility(true);
};
const hideDatePicker = () =&gt; {
setDatePickerVisibility(false);
};
const navigation = useNavigation();
const NationalityData = [&quot;Football&quot;, &quot;Cricket&quot;, &quot;Programmming&quot;, &quot;Coding&quot;];
const [refreshing, setRefreshing] = useState(false);
const onRefresh = useCallback(() =&gt; {
setRefreshing(true);
setTimeout(() =&gt; {
setRefreshing(false);
}, 2000);
}, []);
const statusBarHeight = Platform.OS === &quot;ios&quot; ? 50 : StatusBar.currentHeight;
return (
&lt;KeyboardAvoidingView behavior=&quot;padding&quot;&gt;
&lt;HideKeyboard&gt;
&lt;View
style={{
height: &quot;100%&quot;,
width: &quot;100%&quot;,
backgroundColor: &quot;#f1be63&quot;,
}}
&gt;
&lt;View
style={{ backgroundColor: &quot;#f1be63&quot;, height: statusBarHeight }}
&gt;
&lt;StatusBar barStyle=&quot;dark-content&quot; /&gt;
&lt;/View&gt;
&lt;ScrollView
contentContainerStyle={styles.rootContainer}
refreshControl={
&lt;RefreshControl
refreshing={refreshing}
onRefresh={onRefresh}
/&gt;
}
&gt;
&lt;Image
source={require(&quot;../assets/aeroplane.png&quot;)}
style={styles.image}
resizeMode=&quot;contain&quot;
/&gt;
&lt;Text style={styles.header}&gt;Let&#39;s get you set up&lt;/Text&gt;
&lt;Text style={styles.lowerHeader}&gt;
(we promise that it won&#39;t take long)
&lt;/Text&gt;
&lt;View style={[styles.textFieldsContainer]}&gt;
&lt;View style={{ alignItems: &quot;center&quot; }}&gt;
&lt;Input
isLabel={true}
label=&quot;Preferred Pronoun&quot;
placeholder=&quot;He/Him&quot;
onChangeText={(text) =&gt; {
s_context.updateFormData(&quot;pref_pronoun&quot;, text);
}}
/&gt;
&lt;Input
isLabel={true}
label=&quot;First Name&quot;
placeholder=&quot;Cameron&quot;
onChangeText={(text) =&gt; {
s_context.updateFormData(&quot;first_name&quot;, text);
}}
/&gt;
&lt;Input
isLabel={true}
label=&quot;Last Name&quot;
placeholder=&quot;Cox&quot;
onChangeText={(text) =&gt; {
s_context.updateFormData(&quot;last_name&quot;, text);
}}
/&gt;
&lt;View
style={{
backgroundColor: &quot;white&quot;,
width: &quot;80%&quot;,
borderRadius: 5,
marginTop: 10,
}}
&gt;
&lt;Button
title=&quot;Date of Birth&quot;
onPress={showDatePicker}
color=&quot;gray&quot;
/&gt;
&lt;/View&gt;
&lt;DateTimePickerModal
isVisible={isDatePickerVisible}
mode=&quot;date&quot;
onConfirm={(date) =&gt; {
s_context.updateFormData(&#39;dob&#39;, date);
hideDatePicker();
}}
onCancel={hideDatePicker}
buttonTextColorIOS=&quot;white&quot;
pickerContainerStyleIOS={{ backgroundColor: &quot;#D89D35&quot; }}
isDarkModeEnabled
/&gt;
&lt;/View&gt;
&lt;View style={{ alignItems: &quot;center&quot; }}&gt;
&lt;DropDown
data={NationalityData}
placeholder=&quot;Nationality&quot;
onSelect={(selectedItem, index) =&gt; {
s_context.updateFormData(&quot;nationality&quot;, selectedItem);
}}
/&gt;
&lt;DropDown
data={NationalityData}
placeholder=&quot;University&quot;
onSelect={(selectedItem, index) =&gt; {
s_context.updateFormData(&quot;university&quot;, selectedItem);
}}
/&gt;
&lt;DropDown
data={NationalityData}
placeholder=&quot;Course&quot;
onSelect={(selectedItem, index) =&gt; {
s_context.updateFormData(&quot;course&quot;, selectedItem);
}}
/&gt;
&lt;DropDown
data={NationalityData}
placeholder=&quot;HomeTown City&quot;
onSelect={(selectedItem, index) =&gt; {
s_context.updateFormData(&quot;homeCity&quot;, selectedItem);
}}
/&gt;
&lt;CustomButton
isBorder={true}
title=&quot;Next&quot;
onPress={() =&gt; {
navigation.navigate(&quot;SignUp2&quot;);
}}
/&gt;
&lt;/View&gt;
&lt;/View&gt;
&lt;/ScrollView&gt;
&lt;/View&gt;
&lt;/HideKeyboard&gt;
&lt;/KeyboardAvoidingView&gt;
);
}
const styles = StyleSheet.create({
rootContainer: {
height: &quot;125%&quot;,
justifyContent: &quot;flex-start&quot;,
alignItems: &quot;center&quot;,
marginTop: 24,
},
textFieldsContainer: {
width: &quot;100%&quot;,
flex: 1,
},
image: {
width: &quot;25%&quot;,
height: &quot;10%&quot;,
marginTop: 24,
},
header: {
color: &quot;white&quot;,
fontSize: 26,
fontWeight: &quot;bold&quot;,
marginVertical: 6,
},
lowerHeader: {
color: &quot;white&quot;,
fontSize: 12,
marginBottom: 24,
},
});
export default SignUpForm1;

SignUpForm2.js


import {
View,
Text,
TouchableWithoutFeedback,
StyleSheet,
StatusBar,
ScrollView,
} from &quot;react-native&quot;;
import { KeyboardAvoidingView } from &quot;react-native&quot;;
import { Avatar } from &quot;react-native-elements&quot;;
import Input from &quot;./Input&quot;;
import DropDown from &quot;./DropDown&quot;;
import { Keyboard } from &quot;react-native&quot;;
import { Platform } from &quot;react-native&quot;;
import { useNavigation } from &quot;@react-navigation/native&quot;;
import CustomButton from &quot;./CustomButton&quot;;
import { useState, useContext } from &quot;react&quot;;
import { createNewUser } from &quot;./util/auth&quot;;
import { SignUpContext, UserData } from &quot;./GlobalUtil/UserData&quot;;
const HideKeyboard = ({ children }) =&gt; (
&lt;TouchableWithoutFeedback onPress={() =&gt; Keyboard.dismiss()}&gt;
{children}
&lt;/TouchableWithoutFeedback&gt;
);
function SignUpForm2() {
const s_context = useContext(SignUpContext);
async function FinishBtnHandler()
{
console.log(&quot;Creating New User&quot;);
console.log(&quot;Email: &quot; + emailText.trim());
console.log(&quot;Password: &quot; + passwordText.trim());
await createNewUser(emailText.trim(), passwordText.trim());
}
const navigation = useNavigation();
const hobbiesData = [&quot;Football&quot;, &quot;Cricket&quot;, &quot;Programmming&quot;, &quot;Coding&quot;];
const [emailText, setEmailText] = useState(&quot;&quot;);
function handleEmailText(newText) {
console.log(&quot;Email: &quot; + newText);
setEmailText(newText);
}
const [passwordText, setPasswordText] = useState(&quot;&quot;);
function handlePasswordText(newText) {
console.log(&quot;Password: &quot; + newText);
setPasswordText(newText);
}
function avatarPressHandler() {
console.log(&quot;Pressed!&quot;);
}
const statusBarHeight = Platform.OS === &quot;ios&quot; ? 50 : StatusBar.currentHeight;
return (
&lt;KeyboardAvoidingView behavior=&quot;padding&quot; style={{ flex: 1 }}&gt;
&lt;HideKeyboard&gt;
&lt;ScrollView&gt;
&lt;View
style={{
position: &quot;absolute&quot;,
top: 0,
left: 0,
right: 0,
zIndex: 999,
}}
&gt;
&lt;View
style={{
backgroundColor: &quot;#f1be63&quot;,
height: statusBarHeight,
}}
&gt;
&lt;StatusBar barStyle=&quot;dark-content&quot; /&gt;
&lt;/View&gt;
&lt;/View&gt;
&lt;View style={[styles.rootContainer, { paddingBottom: 48 }]}&gt;
&lt;View style={styles.lowerContainer}&gt;
&lt;Text style={styles.primaryText}&gt;You&#39;re almost there!&lt;/Text&gt;
&lt;Avatar
rounded
size={170}
containerStyle={{ alignSelf: &quot;center&quot;, marginTop: 24 }}
//icon={{ name: &quot;user&quot;, type: &quot;font-awesome&quot; }}
overlayContainerStyle={{ backgroundColor: &quot;#f1be63&quot; }}
source={{
uri: &quot;https://cdn.pixabay.com/photo/2019/11/03/20/11/portrait-4599553__340.jpg&quot;,
}}
&gt;
&lt;Avatar.Accessory size={20} onPress={avatarPressHandler} /&gt;
&lt;/Avatar&gt;
&lt;Text
style={[
styles.secondaryText,
{ marginBottom: 8, marginTop: 16 },
]}
&gt;
Express yourself &amp; customize your avatar
&lt;/Text&gt;
&lt;Input
isLabel={true}
label=&quot;Student Email&quot;
placeholder=&quot;cce22rnu@uea.ac.uk&quot;
onChangeText={handleEmailText}
defaultValue={emailText}
/&gt;
&lt;Input
isLabel={true}
label=&quot;Create Password&quot;
placeholder=&quot;iLoveyoushakila123&quot;
onChangeText={handlePasswordText}
defaultValue={passwordText}
/&gt;
&lt;Input
isLabel={true}
label=&quot;Confirm Password&quot;
placeholder=&quot;iLoveyoushakila123&quot;
/&gt;
&lt;Text style={styles.secondaryText}&gt;
Now the exciting part - select your top 5 hobbies
&lt;/Text&gt;
&lt;View style={{ alignItems: &quot;center&quot;, marginTop: 16 }}&gt;
&lt;DropDown
data={hobbiesData}
onSelect={(selectedItem, index) =&gt; {
s_context.updateFormData(&quot;hobby_1&quot;, selectedItem);
}}
/&gt;
&lt;DropDown data={hobbiesData} onSelect={(selectedItem, index) =&gt; {
s_context.updateFormData(&quot;hobby_2&quot;, selectedItem);
}}/&gt;
&lt;DropDown data={hobbiesData} onSelect={(selectedItem, index) =&gt; {
s_context.updateFormData(&quot;hobby_3&quot;, selectedItem);
}}/&gt;
&lt;DropDown data={hobbiesData} onSelect={(selectedItem, index) =&gt; {
s_context.updateFormData(&quot;hobby_4&quot;, selectedItem);
}}/&gt;
&lt;DropDown data={hobbiesData} onSelect={(selectedItem, index) =&gt; {
s_context.updateFormData(&quot;hobby_5&quot;, selectedItem);
}}/&gt;
&lt;CustomButton
isBorder={true}
title=&quot;Finish&quot;
/*onPress={()=&gt;{navigation.navigate(&quot;ConfirmId&quot;)}}*/ onPress={
FinishBtnHandler
}
/&gt;
&lt;/View&gt;
&lt;/View&gt;
&lt;/View&gt;
&lt;/ScrollView&gt;
&lt;/HideKeyboard&gt;
&lt;/KeyboardAvoidingView&gt;
);
}
const styles = StyleSheet.create({
rootContainer: {
flex: 1,
justifyContent: &quot;flex-start&quot;,
alignItems: &quot;center&quot;,
backgroundColor: &quot;#f1be63&quot;,
marginTop: 48,
backgroundColor: &quot;#f1be63&quot;,
},
lowerContainer: {
flex: 1,
width: &quot;100%&quot;,
alignItems: &quot;center&quot;,
},
primaryText: {
color: &quot;white&quot;,
fontSize: 24,
fontWeight: &quot;bold&quot;,
},
secondaryText: {
marginTop: 8,
color: &quot;white&quot;,
fontSize: 12,
fontWeight: &quot;bold&quot;,
},
});
export default SignUpForm2;

React Context is not updating Data.

答案1

得分: 3

只返回翻译好的部分:

  1. You need to pass your userDetails state variable to the context, not the initial state value.
    你需要将userDetails状态变量传递给上下文,而不是初始的state值。

  2. Passing the initial state object will not see any updates you make.
    传递初始状态对象将不会看到你所做的任何更新。

  3. Also, you should use the functional updates format to dynamically set properties in your state.
    另外,你应该使用函数更新格式来动态设置状态中的属性。

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

  5. Finally, console logging state is a pointless exercise that often gives unexpected results. Just don't do it.
    最后,记录状态到控制台是一个毫无意义的操作,通常会导致意外的结果。不要这样做。

英文:

You need to pass your userDetails state variable to the context, not the initial state value

&lt;SignUpContext.Provider value={{ state: userDetails, updateFormData }}&gt;
{props.children}
&lt;/SignUpContext.Provider&gt;

Passing the initial state object will not see any updates you make.

Also, you should use the functional updates format to dynamically set properties in your state

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

Finally, console logging state is a pointless exercise that often gives unexpected results. Just don't do it

huangapple
  • 本文由 发表于 2023年2月14日 06:35:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/75441833.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定