React Context is not updating Data - javascript

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 "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", "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.log("Creating New User");
console.log("Email: " + emailText.trim());
console.log("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.log("Email: " + newText);
setEmailText(newText);
}
const [passwordText, setPasswordText] = useState("");
function handlePasswordText(newText) {
console.log("Password: " + newText);
setPasswordText(newText);
}
function avatarPressHandler() {
console.log("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;

You need to pass your userDetails state variable to the context, not the initial state value
<SignUpContext.Provider value={{ state: userDetails, updateFormData }}>
{props.children}
</SignUpContext.Provider>
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) => ({ ...prev, [field]: value }));
Finally, console logging state is a pointless exercise that often gives unexpected results. Just don't do it

The issue is that you are using state instead of userDetails in the updateFormData function. The state variable is never updated and remains the same initial value. To fix this, you should use setDetails instead of setState in the updateFormData function.
const updateFormData = (field, value) => {
setDetails({ ...userDetails, [field]: value });
console.log(userDetails);
};
Also, you are passing state in the SignUpContext.Provider value. You should pass userDetails instead of state.
return (
<SignUpContext.Provider value={{ userDetails, updateFormData }}>
{props.children}
</SignUpContext.Provider>
);

Related

Displaying a Image from the Camera

I am relatively new to React-Native and mobile app development. I am trying to create a clone of Instagram. And in the post screen what I do is I have a button Camera and once I click on it, that should take me to CameraView screen. And in the CameraView screen I will take a picture using expo-camera and save the picture in a variable. So here, I want to export the picture and then import it in my Post screen, so that the user can have a preview of what the picture looks like before uploading. And another thing to note is that, the Post screen will by default have a Placeholder image and once the image is taken the placeholder image has to be replaced with the image.
I tried this code but it didnt work.
My Post screen :-
import { View, Text, Image, TextInput } from 'react-native';
import React, { useState, useEffect } from 'react'
import * as Yup from 'yup';
import { Formik } from 'formik'
import { Button, Divider } from 'react-native-elements';
import { useNavigation } from '#react-navigation/native';
import CameraView, { takePicture } from '../../screens/CameraView';
const PLACEHOLDER_IMG = require('../../assets/defImg.png')
const uploadPostSchema = Yup.object().shape({
caption: Yup.string().max(2200, 'Caption cannot exceed character limit.')
})
const FormikPostUploader = ({route}) => {
const [thumbnailUrl, setThumbnailUrl] = useState(PLACEHOLDER_IMG)
const navigation = useNavigation()
const handleCameraPress = () => {
UserImage = takePicture()
setThumbnailUrl(UserImage)
navigation.navigate('CameraView')
}
return (
<Formik
initialValues={{ imageUrl: '', caption:'' }}
onSubmit={(values) => console.log(values)}
validationSchema={uploadPostSchema}
validateOnMount={true}>
{({
handleBlur,
handleChange,
handleSubmit,
values,
errors,
isvalid
}) => (
<>
<View style={{ margin: 20, justifyContent: 'space-between', flexDirection: 'row' }}>
<Image source={thumbnailUrl} />
<View style={{ flex: 1, margin: 15 }}>
<TextInput
placeholder='Write a caption...'
placeholderTextColor='gray'
multiline={true}
style={{ color: 'white', fontSize: 17 }}
onChangeText={handleChange('caption')}
onBlur={handleBlur('caption')}
value={values.caption}
/>
</View>
</View>
<Divider width={0.5} orientation='vertical'/>
<View style={{ alignItems: 'center', marginTop: 15 }}>
<Text style={{ fontSize: 18, fontWeight: 'bold', color: 'white' }}>Choose Image</Text>
</View>
<View style={{ justifyContent: 'space-between', flexDirection: 'column', margin: 20 }}>
<View style={{ justifyContent: 'space-between', flexDirection: 'row', margin: 30 }}>
<Button title='Camera' onPress={handleCameraPress}/>
<Button title='Gallery' onPress={() => navigation.navigate('GalleryView')} />
</View>
<Button onPress={handleSubmit} title='Post' disabled={isvalid} />
</View>
</>
)}
</Formik>
)
}
export default FormikPostUploader
And my CameraView screen :-
import { View, Text, Image, StyleSheet, Button } from 'react-native'
import React, {useState, useEffect} from 'react'
import { Camera } from 'expo-camera'
import { TouchableOpacity } from 'react-native'
import { useNavigation } from '#react-navigation/native'
import { PLACEHOLDER_IMG } from '../components/newPost/FormikPostUploader'
export const takePicture = async(camera) => {
const data = await camera.takePictureAsync(null)
return data.uri
}
const Header = () =>{
const navigation = useNavigation()
return (
<View style = {styles.headerContainer}>
<TouchableOpacity style = {{marginBottom:15}} onPress={() => navigation.goBack()}>
<Image source = {require('../assets/back.png')} style = {{width:35, height:35, margin:20}}/>
</TouchableOpacity>
<Text style={{color:'white', fontWeight: '700', fontSize:20, marginRight: 25, marginTop:35, marginBottom:15}}>New Post</Text>
<Text> </Text>
</View>
)
}
const CameraView = () => {
const UserImage = takePicture()
const navigation = useNavigation()
const [hasCameraPermission, setHasCameraPermission] = useState(null)
const [thumbnailUrl, setThumbnailUrl] = useState(PLACEHOLDER_IMG)
const [camera, setCamera] = useState(null)
const [type, setType] = useState(Camera.Constants.Type.back)
const captureImage = async () => {
if (camera) {
const UserImage = await takePicture(camera)
setThumbnailUrl(UserImage)
}
}
useEffect(() => {
(async() => {
const cameraStatus = await Camera.requestCameraPermissionsAsync()
setHasCameraPermission(cameraStatus.status === 'granted')})()},
[])
if (hasCameraPermission === null) {
return <View/>
}
if (hasCameraPermission === false){
return <Text>Enable access for Camera to proceed</Text>
}
return (
<View style={{ flex: 1, backgroundColor: 'black'}}>
<Header/>
<Camera
ref = {ref => setCamera(ref)}
style={styles.fixedRatio}
type={type}
ratio={'1:1'}/>
<View style = {styles.cameraContainer}>
<TouchableOpacity onPress={() => {setType(type === Camera.Constants.Type.back ? Camera.Constants.Type.front : Camera.Constants.Type.back)}}>
<Image source={require('../assets/turn-camera.png')} style = {{width:70, height:70, margin: 15}}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => {captureImage(), navigation.goBack(), console.log(UserImage)}}>
<Image source={require('../assets/camera-shutter.png')} style = {{width:70, height:70, marginRight:60}}/>
</TouchableOpacity>
</View>
</View>
)
}
const styles = StyleSheet.create({
cameraContainer: {
flex:0.15,
backgroundColor: 'black',
flexDirection:'row',
justifyContent: 'space-between',
alignItems: 'center',
},
fixedRatio: {
flex:0.99,
aspectRatio:0.9
},
headerContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
backgroundColor:'black'
},
icon: {
width:25,
height: 25,
marginHorizontal:15,
marginTop:30,
},
iconContainer: {
flexDirection:'row',
justifyContent: 'space-between',
height:50,
},
}
)
export default CameraView
Am I doing anything wrong. Can you help me fix this. Thanks in advance!

data size bigger than 1 has rendering issue

data that worked looks like this
(I used JSON.stringify function to see how the data looks like)
[{"_id":"612e60c4ce136a1f4454c938", "individualPurchasePrice":9800,"teamPurchasePrice":640, "eventDealCategory":"DysonHairDryer"}]
below is the data that didn't work
[{"_id":"612e60c4ce136a1f4454c938", "individualPurchasePrice":9800,"teamPurchasePrice":640, "eventDealCategory":"JMWHairDryer"}, {"_id":"612e60c4ce136a1f4454c938", "individualPurchasePrice":9800,"teamPurchasePrice":640, "eventDealCategory":"JMWHairDryer"},]
this is the error message
Element type is invalid:expected a string (for built-in components) or a class/function (for composite components) but got: object.
import React from 'react'
import { SafeAreaView, View, Dimensions, Text, ScrollView } from 'react-native'
import ItemStore from '../stores/ItemStore'
import ImageManager from '../images/ImageManager'
import ItemListWithoutCategory from '../components/item/ItemListWithoutCategory'
import TimeDealItemComponent from '../components/item/TimeDealItemComponent'
const dims = Dimensions.get('window')
const TimeDealItemScreen = ({ route, navigation }) => {
const { eventDealCategoryName } = route.params
return (
<SafeAreaView style={{ flex: 1 }}>
<ScrollView style={{ height: 40, backgroundColor: 'red' }}>
<ImageManager
source='TimeDealGradientImage'
style={{
position: 'absolute',
width: '100%',
height: '100%',
top: 0,
bottom: 0,
left: 0,
right: 0,
}}
/>
<ItemListWithoutCategory
isFrom='TimeDealItemScreen'
ItemSeparatorComponent={<View style={{ height: 16 }} />}
ListFooterComponent={
<>
<View style={{ height: 16, backgroundColor: 'transparent' }} />
</>
}
data={ItemStore?.eventDealItems?.filter(
(item) => item.eventDealCategory === eventDealCategory,
)}
renderItem={({ item, index }) => (
<View style={{ paddingHorizontal: 8 }}>
<TimeDealItemComponent item={item} index={index} />
</View>
)}
ListFooterComponent={
<>
<View style={{ height: 16, backgroundColor: 'transparent' }} />
</>
}
/>
</ScrollView>
</SafeAreaView>
)
}
export default TimeDealItemScreen
import React, { useState, useRef, useEffect, useCallback } from 'react'
import { FlatList } from 'react-native'
import ItemStore from '../../stores/ItemStore'
import { observer } from 'mobx-react-lite'
import UserStore from '../../stores/UserStore'
import { useNavigation } from '#react-navigation/native'
import viewabilityConfig from '../config/viewabilityConfig'
const ItemListWithoutCategory = observer(
({
ListEmptyComponent,
ListFooterComponent,
ItemSeparatorComponent,
data,
renderItem,
ListHeaderComponent,
isFrom,
ref,
onEndReached,
numColumns,
}) => {
const navigation = useNavigation()
const onViewableItemsChanged = useCallback(
({ viewableItems, changed }) => {
changed.forEach((item) => {
if (item.isViewable) {
const addedImpressionItems = {
itemId: item.item?._id,
itemTitle: item.item?.itemTitle,
loggedAt: new Date(),
isFrom,
}
ItemStore.addImpressionItems(addedImpressionItems)
}
})
},
[ItemStore.screenOnFocusMyOrder],
)
const viewabilityConfigCallbackPairs = useRef([
{ viewabilityConfig, onViewableItemsChanged },
])
return (
<FlatList
ref={ref}
viewabilityConfigCallbackPairs={viewabilityConfigCallbackPairs.current}
data={data}
ListHeaderComponent={ListHeaderComponent}
renderItem={renderItem}
keyExtractor={(item, index) => item?._id + index.toString()}
ListEmptyComponent={ListEmptyComponent}
ListFooterComponent={ListFooterComponent}
ItemSeparatorComponent={ItemSeparatorComponent}
onEndReached={onEndReached}
numColumns={numColumns}
/>
)
},
)
export default ItemListWithoutCategory
import React, { useState, useEffect } from 'react'
import { View, TouchableOpacity, Dimensions } from 'react-native'
import BlackText from '../texts/BlackText'
import GrayText from '../texts/GrayText'
import BasicButton from '../buttons/BasicButton'
import { observer } from 'mobx-react-lite'
import UserStore from '../../stores/UserStore'
import OrderStore from '../../stores/OrderStore'
import ImageManager from '../../images/ImageManager'
import backendApis from '../../utils/backendApis'
import { useNavigation } from '#react-navigation/native'
import ItemStore from '../../stores/ItemStore'
import RedText from '../texts/RedText'
import FastImage from 'react-native-fast-image'
import ImageTextTimer from '../texts/ImageTextTimer'
import commaNumber from 'comma-number'
const dims = Dimensions.get('window')
const TimeDealItemComponent = observer(({ item, index }) => {
const FULL_GAGE_WIDTH = 70
const CURRENT_GAGE_WIDTH = item.stockSoldPercentage
const GAGE_HEIGHT = 16
const navigation = useNavigation()
const TRANSPARENT_GRAY_CIRCLE_SIZE = 80
const [eventDealStatusHere, setEventDealStatusHere] = useState(0)
const [orderRecord, setOrderRecord] = useState('unpurchased')
useEffect(() => {
const eventStartedDate = new Date(item.eventDealStartedAt) // x
const now = new Date().getTime() // y
const oneDayTerm = 1000 * 60 * 60 * 24 * 1 // 7일
const stockleft = item.eventDealStock - item.totalOrderQuantity
if (eventStartedDate > new Date(now)) {
setEventDealStatusHere('preOpened')
} else if (
eventStartedDate < new Date(now) &&
eventStartedDate > new Date(now - oneDayTerm) &&
stockleft > 0
) {
setEventDealStatusHere('opened')
} else if (
eventStartedDate < new Date(now) &&
eventStartedDate > new Date(now - oneDayTerm) &&
stockleft <= 0
) {
setEventDealStatusHere('temporarilyClosed')
} else setEventDealStatusHere('closed')
}, [])
useEffect(() => {
if (
OrderStore.loadedUserOrdersList.find(
(order) =>
[
'pre-shipping',
'shipping',
'exchanging',
'arrived',
'reviewed',
].includes(order.status) && item._id === order.itemInfo.itemId,
)
) {
setOrderRecord('purchased')
} else {
setOrderRecord('unpurchased')
}
}, [OrderStore.loadedUserOrdersList])
const StockInfoTextComponent = ({ text }) => {
return (
<View
style={{
flexDirection: 'row',
alignContent: 'center',
// backgroundColor: 'grey',
}}
>
<GrayText text={text} fontSize={14} dark numberOfLines={1} />
</View>
)
}
const StockInfoText = () => {
if (eventDealStatusHere === 'preOpened') {
return (
<StockInfoTextComponent
text={`${commaNumber(item.eventDealStock)}개 입고 예정`}
/>
)
}
if (eventDealStatusHere === 'temporarilyClosed') {
return <StockInfoTextComponent text='일시적 물량 소진' />
}
if (eventDealStatusHere === 'closed') {
return <StockInfoTextComponent text='재고 전량 소진' />
}
return <></>
}
return (
<View style={{ width: '100%' }}>
<View
style={{
flex: 1,
width: '100%',
}}
>
<TouchableOpacity
style={{
backgroundColor: 'white',
marginTop: 12,
padding: 8,
borderRadius: 8,
}}
activeOpacity={1.0}
onPress={() => {
if (ItemStore.isLoadingItemScreen) {
return
}
ItemStore.setIsLoadingItemScreen(true)
navigation.push('MainStackDItemScreen', {
itemId: item._id,
itemInfo: item.itemInfo,
enteringComponent: 'TimeDealItemComponent',
})
setTimeout(() => {
ItemStore.setIsLoadingItemScreen(false)
}, 1000)
}}
>
<View
style={{
flexDirection: 'row',
marginTop: 4,
borderRadius: 4,
}}
>
<View
style={{
flex: 2,
flexDirection: 'column',
paddingHorizontal: 8,
}}
>
<View
style={{
paddingBottom: 8,
flexDirection: 'row',
paddingRight: 16,
}}
>
<BlackText
text={item.itemTitle}
fontSize={16}
numberOfLines={2}
/>
</View>
{/* 1.아이템타이틀 끝 */}
{/* 7. 게이지 시작 */}
<View
style={{
alignContent: 'center',
justifyContent: 'center',
}}
>
{eventDealStatusHere === 'opened' && (
<View
style={{
flexDirection: 'row',
alignItems: 'center',
}}
>
<View
style={{
backgroundColor: '#E89FA1',
height: GAGE_HEIGHT,
width: FULL_GAGE_WIDTH,
borderRadius: 12,
}}
>
<View
style={{
backgroundColor: '#EC4F48',
height: GAGE_HEIGHT,
width: FULL_GAGE_WIDTH * CURRENT_GAGE_WIDTH,
borderRadius: 12,
}}
/>
</View>
{/* opened */}
{eventDealStatusHere === 'opened' && (
<View
style={{
flexDirection: 'row',
alignContent: 'center',
paddingLeft: 8,
// backgroundColor: 'grey',
}}
>
<GrayText
text={item.stockLeft}
fontSize={12}
numberOfLines={1}
/>
<GrayText
text='개 남음'
fontSize={12}
numberOfLines={1}
/>
</View>
)}
</View>
)}
</View>
{/* 7. 게이지 끝 */}
{orderRecord === 'purchased' && (
<View
style={{
borderRadius: 4,
paddingTop: 10,
}}
>
<>
<BasicButton
width={30}
text='이미 구매하신 아이템입니다.'
eventDealClosed
backgroundColor='#B3B4B7'
/>
</>
</View>
)}
</TouchableOpacity>
</View>
</View>
)
})
export default TimeDealItemComponent
below is the data that didn't work
[{"_id":"612e60c4ce136a1f4454c938", "eventDealCategory":"JMWHairDryer"}, {"_id":"612e60c4ce136a1f4454c938", "eventDealCategory":"JMWHairDryer"},]
It does not work in second example because instead of one object you have array of objects. To render them you need to map throught array.

React Native : onPress not working for authentification

I'm transitionning from React to React Native, and so far got the basics. In my application I'm trying to implement the authentification.
I already setup my working APIs for the login and registration and verified them using POSTMAN.
The problem here is for some reason onPress={onSignInHandler} doesn't do anything. Normally in React I would put onClick={onSignInHandler} and everything will be working fine.
I would like, when the Login is pressed, execute the axios request, and then redirect to for example "Myprofil.js" component or atleast display and alert to see if it's working. As far as I know React Native uses react-navigation instead of react-router.
app.js:
import * as React from 'react';
import { View, Text } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import Login from './src/views/Login';
import Signup from './src/views/Signup ';
import MyProfil from './src/views/MyProfil';
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Login" screenOptions={{
headerShown: false
}}>
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="Signup " component={Signup} />
<Stack.Screen name="MyProfil" component={MyProfil} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
login.js :
import React, { Component, UseState } from 'react';
import { View, Text, TextInput, StyleSheet, Image, Dimensions, Alert } from 'react-native';
import axios from "axios";
const { width, height } = Dimensions.get('window');
function Login() {
const [state, setState] = React.useState({
msg: "",
isLoading: false,
redirect: false,
errMsgEmail: "",
errMsgPwd: "",
errMsg: "",
});
const [email, setEmail] = React.useState("");
const [password, setPassword] = React.useState("");
const handleChangeEmail = (event) => {
setEmail(event.target.value);
};
const handleChangePassword = (event) => {
setPassword(event.target.value);
};
function onSignInHandler() {
const infos = {
email: email,
password: password,
};
axios
.post("http://127.0.0.1:8000/api/login", infos)
.then((response) => {
if (response.data.status === 200) {
localStorage.setItem("isLoggedIn", true);
localStorage.setItem("userData", JSON.stringify(response.data.data));
this.setState({
msg: response.data.message,
redirect: true,
});
}
if (
response.data.status === "failed" &&
response.data.success === undefined
) {
this.setState({
errMsgEmail: response.data.validation_error.email,
errMsgPwd: response.data.validation_error.password,
});
setTimeout(() => {
this.setState({ errMsgEmail: "", errMsgPwd: "" });
}, 2000);
} else if (
response.data.status === "failed" &&
response.data.success === false
) {
this.setState({
errMsg: response.data.message,
});
setTimeout(() => {
this.setState({ errMsg: "" });
}, 2000);
}
})
.catch((error) => {
console.log(error);
});
};
return (
<View
style={{
flex: 1,
backgroundColor: 'white',
justifyContent: 'flex-end'
}}
>
<View style={{ ...StyleSheet.absoluteFill }}>
<Image
source={require('../images/bg.jpg')}
style={{ flex: 1, height: null, width: null }}
>
</Image>
</View>
<View style={{ height: height / 2, justifyContent: 'center' }}>
<View>
<Text style={{ fontSize: 20, fontWeight: 'bold', color:"#ffffff",fontSize: 30, marginHorizontal: 40,marginVertical: 10, }}>Bienvenue !</Text>
</View>
<View style={styles.button}>
<TextInput placeholder="E-mail " style={{ fontSize: 20, fontWeight: 'bold' }} value={email} onChange={handleChangeEmail}></TextInput>
</View>
<View style={styles.button}>
<TextInput placeholder="Password" style={{ fontSize: 20, fontWeight: 'bold' }} secureTextEntry={true} value={password} onChange={handleChangePassword}></TextInput>
</View>
<View style={{alignItems: 'center',justifyContent: 'center', marginTop: 20}}>
<Text style={{ fontSize: 20, fontWeight: 'bold', color: '#ffffff' }} onPress={onSignInHandler}>
LOGIN
</Text>
</View>
</View>
</View>
);
}
export default Login;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
button: {
backgroundColor: 'white',
height: 50,
marginHorizontal: 30,
borderRadius: 35,
alignItems: 'center',
justifyContent: 'center',
marginVertical: 10,
}
});
Instead of using onPress for Text component wrap it with a TouchableOpacity and use the onPress of the TouchableOpacity
<TouchableOpacity onPress={onSignInHandler}>
<Text style={{ fontSize: 20, fontWeight: 'bold', color: '#ffffff' }} title="Profil" >LOGIN</Text>
</TouchableOpacity>
Change your
function onSignInHandler() {
to
const onSignInHandler = () => {

How to search mapped list in react native

I have been finding it very difficult to search a mapped list in react native. Actually, doing that with a Flatlist would be very easy for me, but this is really giving me a headache. I hope someone will be able to help me out.
So, the code looks like this
import React, { Component, useState } from 'react';
import { Button, Animated, Share, ScrollView,
ImageBackground, StyleSheet, View} from "react-native";
import { Container, Header, Content, ListItem, Item, Input, Text, Icon, Left, Body, Right, Switch } from 'native-base';
const Auslawpart = ({ route, navigation}) => {
const {parts, hereme} = route.params;
const [search, setSearch] = useState('');
const [filteredDataSource, setFilteredDataSource] = useState(parts);
const filterSearch = (text) => {
const newData = parts.filter((part)=>{
const itemData = part.name.toUpperCase()
const textData = text.toUpperCase()
return itemData.indexOf(textData)>-1
});
setFilteredDataSource(newData);
setSearch(text);
}
return (
<Container>
<Animated.View
style={{
transform:[
{translateY:translateY }
],
elevation:4,
zIndex:100,
}}
>
<View style={{
// marginTop:Constant.statusBarHeight,
position:"absolute",
top:0,
left:0,
right:0,
bottom: 0,
height: 50,
backgroundColor:"#f0f0f0",
borderBottomWidth: 1,
borderBottomColor: '#BDC3C7',
flexDirection:"row",
justifyContent:"space-between",
elevation: 4,
}}>
<View style={{margin: 10, flex: 1 }}>
<TouchableOpacity onPress={() => navigation.goBack()}>
<Icon type="MaterialIcons" name="arrow-back" style={{ left: 10, }}
size={50} />
</TouchableOpacity>
</View>
<View style={{
justifyContent:"space-around",
margin: 4,
flex: 1,
marginLeft:0,
}}>
<Text numberOfLines={3} style={{fontSize:10,
alignSelf: 'flex-end', color:"#212F3C",
padding: 2}}>{hereme}</Text>
</View>
</View>
</Animated.View>
<Content style={{marginTop:50}}>
<Item>
<Icon type= "MaterialIcons" />
<Input placeholder="Search legal terms and maxisms"
onChangeText={(text) => filterSearch(text)}
/>
<Icon type="Octicons" name="law" />
</Item>
{parts.map((part) => (
<TouchableOpacity
key={part.name}
>
<ListItem onPress={() =>
navigation.navigate("Auslawcount", {
meaning: part.meaning,
partname: part.name})
}>
<Icon type="Octicons" name="law" />
<Body>
<Text onScroll={(e)=>{
scrollY.setValue(e.nativeEvent.contentOffset.y)
}} style={{ fontSize: 17, fontFamily: "Lato-Regular",}} key={part.name}>{part.name.toUpperCase()}</Text>
</Body>
</ListItem>
</TouchableOpacity>
))}
</Content>
</Container>
);
};
export default Auslawpart;
The data in part.name are passed from another screen to this screen. I am try to make the Input field search through the mapped part.name. can anybody please help me with a solution.
Here is an Example
snack: https://snack.expo.io/#ashwith00/bold-waffles
const data = [
{ name: 'Suleman' },
{ name: 'Sulan' },
{ name: 'Suljan' },
{ name: 'Ram' },
{ name: 'Raj' },
];
const Auslawpart = ({ route, navigation }) => {
const {} = route.params;
const [filteredDataSource, setFilteredDataSource] = useState(parts);
const filterSearch = (text) => {
if (text.length > 0) {
const newList = data.filter((part) => {
const name = part.name.toUpperCase();
const textData = text.toUpperCase();
return name.includes(textData);
});
setFilteredDataSource(newList);
} else {
setFilteredDataSource(parts);
}
};
return (
<View>
<TextInput placeholder="Enter here" onChangeText={filterSearch} />
<ScrollView>
{filteredDataSource.map((item, i) => (
<Text key={i} style={{ paddingVertical: 30 }}>
{item.name}
</Text>
))}
</ScrollView>
</View>
);
};

How to rerender the page on alert ok button

Here in my code I am trying to reload the page on Alert ok button . But its not working . How can I rerender the page on ok button , this is written on same page that I have to reload .
In my code I am sung form and inputfield compont for my login screen . All code is there below . I am tryning to is , when I am getting any respons like wrong username and password in alere then ok button I have to clear my form field . While here ists not happning . For this I am deleting my value mannully.
Please sugget .
import React from 'react';
import { Alert, Dimensions, ImageBackground, Text, View, TouchableOpacity, Platform , StatusBar} from 'react-native';
import Formbox from './ui/form';
import { RegularText, } from './ui/text';
import pkg from '../../package';
import _ from 'lodash';
import { LOGIN_BACKGROUND , LOGIN_BACKGROUND_DARK} from '../images'
import { widthPercentageToDP as wp, heightPercentageToDP as hp } from 'react-native-responsive-screen';
import parentStyle from '../themes/parent.style'
import LottieView from 'lottie-react-native';
const deviceHeight = Dimensions.get('window').height;
const deviceWidth = Dimensions.get('window').width;
const styles = {
imgBG: { width: '100%', height: '100%' },
mainContainer: {
flex: 1,
alignItems: 'stretch',
justifyContent: 'flex-start',
height: deviceHeight,
paddingLeft: 20,
paddingRight: 20
},
logoContainer: { justifyContent: 'center', alignItems: 'center', background: 'red', marginTop: -50 },
logoView: {
borderWidth: 3,
borderColor: '#FFFFFF',
borderRadius: 4,
zIndex: -1,
...Platform.select({
ios: {
shadowOpacity: 0.45,
shadowRadius: 3,
shadowColor: '#090909',
shadowOffset: { height: 1, width: 0 }
},
android: {
elevation: 3
}
})
}
};
export default class Login extends React.Component {
constructor(props) {
super(props);
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (this.props.error) {
if (this.props.error.graphQLErrors[0] !== undefined) {
const errorDetails = _.map(_.split(this.props.error.graphQLErrors[0].message, '#'), _.trim)
const header = errorDetails[0];
const message = errorDetails[1];
Alert.alert(header, message, [{
text: 'OK',
onPress: () => this.props.navigation.push('Auth')
},]);
} else {
Alert.alert('Network Error', this.props.error.networkError.message, [{
text: 'OK',
onPress: () => this.props.navigation.navigate('Auth')
},]);
}
}
}
componentDidMount(){
StatusBar.setBarStyle('dark-content');
}
render() {
let loginForm = [
{ label: 'Username', icon: 'person', type: 'text' },
{ label: 'Password', icon: 'key', type: 'password' }
];
let submitBtn = { label: 'Login', OnSubmit: this.props.onLogin };
let appliedTheme = this.props.theme;
let appliedMode = this.props.mode;
return (
<ImageBackground source={appliedMode === 'light' ? LOGIN_BACKGROUND : LOGIN_BACKGROUND_DARK} style={styles.imgBG}>
<View style={styles.mainContainer}>
<View style={{ flexDirection: 'column', alignContent: 'center', justifyContent: 'center', flex: 1 }}>
<View style={{ flex: 0.75, justifyContent: 'center' }}>
<RegularText text={'Welcome,'} textColor='#57606F' style={{ fontSize: hp('5%') }} />
<RegularText text={'Sign in to continue'} textColor='#ABAFB7' style={{ fontSize: hp('3.5%') }} />
</View>
<View style={{ flex: 2 }}>
<View style={{ flex: 2 }}>
<Formbox
theme={parentStyle[appliedTheme] ? parentStyle[appliedTheme][appliedMode].primaryButtonColor : undefined}
mode={this.props.mode}
formFields={loginForm}
submit={submitBtn}
that={this}
mutation={this.props.token}
/>
<View style={{ height: hp(20), zIndex:10, top: -25}}>
{this.props.loading && (
<LottieView source={require('./animations/login_authentication.json')} autoPlay loop />
)}
</View>
<View style={{top:-70, zIndex:10}}>
{false && <View style={{ alignItems: 'center' }}>
<RegularText text={`v${pkg.version}`} textColor='#ABAFB7' style={{ fontSize: hp('2%') }} />
</View>}
<View style={{ alignItems: 'flex-end' }}>
<View style={{ flexDirection: 'row' }}>
<RegularText text={`New User?`} textColor='#4A494A' style={{ fontSize: hp('2%') }} />
<TouchableOpacity>
<RegularText text={` REGISTER`} textColor={parentStyle[appliedTheme] ? parentStyle[appliedTheme][appliedMode].primaryButtonColor : '#fff'} style={{ fontSize: hp('2%'), fontWeight: 'bold' }} />
</TouchableOpacity>
</View>
</View>
</View>
</View>
</View>
</View>
</View>
</ImageBackground>
);
}
}
////// Form ,js
import React, { Component } from 'react';
import { View, Platform, Dimensions } from 'react-native';
import { PrimaryBtn,PrimaryAbsoluteGradientBtn } from './buttons';
import { InputField, PasswordField } from './inputField';
import { Form } from 'native-base';
import { widthPercentageToDP as wp, heightPercentageToDP as hp } from 'react-native-responsive-screen';
const deviceHeight = Dimensions.get('window').height;
const deviceWidth = Dimensions.get('window').width;
export default class Formbox extends Component {
constructor(props) {
super(props);
}
OnSubmit() {
let { formFields, that, submit, mutation } = this.props;
submit.OnSubmit.bind(that, formFields, mutation)();
}
OnChange(field, target) {
this.props.formFields.forEach(function (formField, indx) {
if (formField.label === field.label) {
formField.value = target;
}
});
}
renderFields(field, indx) {
let { label, icon, type } = field;
if (label && icon) {
if (type === 'password') {
return <PasswordField key={label + indx} type={type ? type : ''} label={label} icon={icon}
OnChange={this.OnChange} that={this} />;
}
return <InputField key={label + indx} type={type ? type : ''} label={label} icon={icon} OnChange={this.OnChange}
that={this} />;
}
}
render() {
let { formFields, submit, that , theme, mode} = this.props;
return (
<View style={{ width: '100%' }}>
<Form style={{ width: '95%' }}>
{formFields.map((field, indx) => this.renderFields(field, indx))}
<View style={{ marginTop: 60 }}>
<PrimaryAbsoluteGradientBtn label={submit.label} OnClick={this.OnSubmit} that={this} backgroundColor={theme}/></View>
</Form>
</View>
);
}
}
/// input fields js
import React, { Component } from 'react';
import { Icon, Input, Item, Label } from 'native-base';
import { View } from 'react-native';
import { DoNothing } from '../services/services';
class InputField extends Component {
constructor(props) {
super(props);
}
render() {
let { label, OnChange, icon, that,type, keyboardType } = this.props;
return (
<View>
<Item floatingLabel>
{icon && <Icon active name={icon}/>}
{label && <Label>{label}</Label>}
<Input
secureTextEntry={type === 'password'}
onChangeText={OnChange ? (e) => OnChange.bind(that, this.props, e)() : DoNothing.bind(this)}
keyboardType={keyboardType || 'default'}
autoCapitalize = 'none'
autoCorrect={false}
/>
</Item>
</View>
);
}
}
class PasswordField extends Component {
constructor(props) {
super(props);
this.state = {
isMasked: true
};
}
_toggleMask = () => {
this.setState({
isMasked: !this.state.isMasked
});
};
render() {
let { label, OnChange, icon, that, type } = this.props;
const { isMasked } = this.state;
return (
<View>
<Item floatingLabel>
{icon && <Icon active name={icon}/>}
<Label>{label}</Label>
<Input
autoCapitalize = 'none'
secureTextEntry={isMasked}
onChangeText={OnChange ? (e) => OnChange.bind(that, this.props, e)() : DoNothing.bind(this)}
/>
<Icon name={isMasked ? "md-eye-off" : "md-eye"} active type="Ionicons" onPress={() => this._toggleMask()}/>
</Item>
</View>
);
}
}
const styles = {
dark: {
color: "#000000"
},
light: {
color: "#EAEAEA"
}
}
export { InputField, PasswordField };
You can either do :
onPress: () => this.props.navigation.push('Auth')
or do something like :
onPress: () => this.setState({name:'random'})
These both will trigger re rendering, Hope it helps. feel free for doubts

Categories

Resources