I have a text input and depending on the text in it will change the xml of <SvgXml />
import React, { useState } from 'react';
import { TextInput, View } from 'react-native';
import { phone } from 'phone'
import { SvgXml } from 'react-native-svg';
import styles from '../styles/home';
function Home() {
const [flagImage, setFlagImage] = useState(null)
const [phoneNumber, setPhoneNumber] = useState(null)
async function handlePhoneNumberChange({ nativeEvent }) {
setPhoneNumber(nativeEvent.text)
const phoneResult = phone(nativeEvent.text)
if (phoneResult.isValid) {
const country = await getCountryData(phoneResult.countryIso2);
if (country.xml) setFlagImage(country.xml);
}
}
return (
<View style={styles.phone} >
{flagImage &&
<View style={styles.phoneFlag} >
{console.log(flagImage)}
<SvgXml xml={flagImage} height={30} width={30} />
</View>
}
<TextInput
value={phoneNumber}
onChange={handlePhoneNumberChange}
keyboardType="numeric"
style={styles.phoneInput}
ref={phoneInputRef}
/>
</View>
);
};
export default Home;
But when the setFlagImage is called the image is not updated, but the log is correct.
If I copy and paste the SVG log into the initial useState the correct SVG is displayed
Related
There are four components on a screen and only three out of four are rendering. <popDown/> is the component that isn't rendering. When I save the specific component's file the components get rendered. Note: I am saving an already fully updated file. It is running with no errors
The Screen
import react from 'react';
import {View,ScrollView} from 'react-native';
import { SafeAreaView, } from 'react-navigation';
import { PrProvider } from '../appFunctions/PrContext';
import PopDown from '../Components/PRForm/popDown';
import RepsWeightTextInput from '../Components/PRForm/RepsWeightTextInput';
import NotesInput from '../Components/PRForm/NotesInput';
import SubmitPr from '../Components/PRForm/SubmitPr';
const PrEnteryScreen = ({}) => {
return(
<View style = {{height:'100%',width:'100%',backgroundColor:'#141212'}}>
<SafeAreaView style = {{alignItems:'center'}}>
{/**
* use context for pr information
*/}
<PrProvider>
<PopDown />
<RepsWeightTextInput/>
<NotesInput/>
<SubmitPr/>
</PrProvider>
</SafeAreaView>
</View>
);
};
export default PrEnteryScreen;
popdown component
import { useContext, useEffect, useState } from "react";
import { TouchableOpacity,StyleSheet,View,LayoutAnimation,UIManager,Platform,useFocusEffect } from "react-native";
import { Children } from "react/cjs/react.production.min";
import SelectExerciseButton, { setIsOpen } from "./SelectExerciseButton";
import SelectExerciseModal from "../../Screens/SelectExerciseModal";
import { EXERCISE_DATA } from "../../Screens/SelectExerciseModal";
import { PrContext, PrProvider } from "../../appFunctions/PrContext";
if (
Platform.OS === "android" &&
UIManager.setLayoutAnimationEnabledExperimental
) {
UIManager.setLayoutAnimationEnabledExperimental(true);
}
const PopDown = () => {
const value = useContext(PrContext)
const [isOpen,setIsOpen] = useState(false)
const [listHeight,setListHeight] = useState(0)
const [textName,setTextName] = useState(value.exercise);//eventually want to change text based on exercise state
const toggleOpen = () => {
setIsOpen(value => !value);
LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
setTextName(value.exercise);
console.log(value.exercise);
}
useEffect(() =>{
EXERCISE_DATA.forEach(()=>{
setListHeight(value => value+50)
})
},[isOpen])
return(
<>
<TouchableOpacity
onPress = {toggleOpen}
>
<SelectExerciseButton />
</TouchableOpacity>
<View>
<SelectExerciseModal style = {isOpen ? styles.show: styles.hidden} listHeight = {listHeight} name = {textName}/>
</View>
</>
)
}
const styles = StyleSheet.create({
hidden:{
height:0,
},
show:{ backgroundColor: '#9B9A9A', width: 200 }
});
export default PopDown;
What I tried
I changed the hidden style height to see if it would render the list that is supposed to pop out of the button. The list did render which means the <selectExerciseButton/> is the only thing not rendering in <popDown/>.
const styles = StyleSheet.create({
hidden:{
height:100,
},
show:{ backgroundColor: '#9B9A9A', width: 200 }
});
<TouchableOpacity
onPress = {toggleOpen}
>
{children}
</TouchableOpacity>
<View>
<SelectExerciseModal style = {isOpen ? styles.show: styles.hidden} listHeight = {listHeight} name = {textName}/>
</View>
<PrProvider>
<PopDown>
<SelectExerciseButton/>
</PopDown>
<RepsWeightTextInput/>
<NotesInput/>
<SubmitPr/>
</PrProvider>
SelectExerciseButton
import { useNavigation,useFocusEffect } from "#react-navigation/native";
import { SafeAreaView, StyleSheet, Text, TouchableOpacity, View,LayoutAnimation } from "react-native";
import { useContext, useState,useEffect } from "react";
import { PrContext } from "../../appFunctions/PrContext";
/**
*
* #returns button that navigates to the a modal to select an exercise
*/
if (
Platform.OS === "android" &&
UIManager.setLayoutAnimationEnabledExperimental
) {
UIManager.setLayoutAnimationEnabledExperimental(true);
}
const SelectExerciseButton = () => {
const value = useContext(PrContext)
return(
<>
<View style = {styles.background}>
<Text style = {styles.Text}> {value.exercise} </Text>
</View>
</>
);
};
styles = StyleSheet.create({
background:{
backgroundColor: '#9B9A9A',
width: 335,
borderRadius:41,
alignItems:'center',
marginHorizontal:25,
height:200,
justifyContent:'center'
},
Text:{
fontWeight:'bold',
fontSize:40,
color:'white',
alignItems:'center'
}
})
export default SelectExerciseButton;
Hi I want to add a function to record the value of input and want to use it in all components and input is in another component and I want to pass a function from App.js to that component but it does not work please help me out \
Please note that the function should be in the App.js passed to Component.js through a Navigator
//App.JS
import React,{useState, useEffect} from "react";
import {
Text,
Link,
HStack,
Center,
Heading,
Switch,
useColorMode,
NativeBaseProvider,
extendTheme,
VStack,
Box,
} from "native-base";
import NativeBaseIcon from "./components/NativeBaseIcon";
import { Platform } from "react-native";
import { createMaterialBottomTabNavigator } from '#react-navigation/material-bottom-tabs';
import HomeScreen from "./Comp/HomeScreen";
import { NavigationContainer } from "#react-navigation/native";
import Location from "./Comp/Location";
export default function App() {
const [api, setapi] = useState(process.env.REACT_APP_API_KEY)
const api_1 = () => {
setapi(process.env.REACT_APP_API_KEY_2)
}
const api_2 = () => {
setapi(process.env.REACT_APP_API_KEY_3)
}
const [value, setvalue] = useState("London")
const handlechange = (e) => {
setvalue(e.target.value)
console.log('value :>> ', value);
}
const Tab = createMaterialBottomTabNavigator();
return (
<NativeBaseProvider>
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen initialParams={{value:value, change:handlechange}} name="Location" component={Location} />
</Tab.Navigator>
</NavigationContainer>
</NativeBaseProvider>
);
}
//Component.js
import { Center, Input, Text } from 'native-base'
import React, {useState} from 'react'
import { ImageBackground } from 'react-native'
import BG from "./Img/BG.png"
export default function Location({ navigation, route }) {
// const [value, setvalue] = useState("London")
// const handlechange = (e) => {
// setvalue(e.target.value)
// console.log('value :>> ', value);
// }
const { change, value } = route.params;
return (
<ImageBackground source={BG}>
<Center minH={"100vh"} w={"90vw"} alignSelf={"center"} alignContent={"center"}>
<Input color={"white"} size="xl" onChange={change} variant="rounded" placeholder="Enter Location" />
<Text color={"white"}></Text>
</Center>
</ImageBackground>
)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
I got stuck here ,
I needed to make a counter into the textinput ,
and I realize ,the counter has conflict with the handleChange.
I have no idea how to modify it ,could you please take a look at my code ?Thank you so much in advance !!
import { StyleSheet, View } from 'react-native'
import React from 'react'
import AppForm from '../components/AppForm'
import * as Yup from 'yup'
import AppFormFieldWithCount from '../components/AppFormFieldWithCount';
const validationSchema = Yup.object().shape({
userName: Yup.string().required("Username can't be empty").label("Username"),
});
const EditScreen = () => {
const handleSubmit = async (userInfo) => {
console.log("receive information",userInfo);
};
return (
<View style={styles.container}>
{/** <TextInputWithCount number={12} maxLength={12} multiline={false} placeholder={"用户名"}/> */}
<AppForm
initialValues={{userName:''}}
validationSchema ={validationSchema}
onSubmit = {handleSubmit}
>
<AppFormFieldWithCount
name = {'userName'}
number ={15}
placeholder={"Username"}
maxLength ={15}
multiline={false}
/>
</AppForm>
</View>
)
}
export default EditScreen
const styles = StyleSheet.create({
container:{
padding:30,
}
})
Below ,it is the formik TextInput :
I have added the setValue for counting the text ,but the textinput will need the handleChange for getting the textinput information .Therefore, it has the conflict here, only one of them works in onChangeText function ...
import { StyleSheet, Text, View,TextInput} from 'react-native'
import React,{useState} from 'react'
import TextInputWithCount from './TextInputWithCount'
import AppErrorMessage from './ErrorMessage'
import { useFormikContext } from 'formik';
import colors from '../config/colors';
const AppFormFieldWithCount = ({name,number,maxLength,multiline,placeholder,...otherProps}) => {
const {setFieldTouched,handleChange,errors,touched} = useFormikContext();
const[value,setValue] = useState('');
return (
<>
<View style={styles.container}>
<TextInput placeholder={placeholder}
style={{flex:1,fontSize:18}}
placeholder = {placeholder}
multiline={multiline}
maxLength={maxLength}
onBlur = {()=>setFieldTouched(name)}
onChangeText = {
handleChange(name)
}
{...otherProps}
/>
<Text>{value === "" ? "0" : value.length}/{number}</Text>
</View>
<AppErrorMessage error={errors[name]} visible={touched[name]} />
</>
)
}
export default AppFormFieldWithCount
const styles = StyleSheet.create({
container:{
flexDirection:'row',
borderRadius:5,
borderWidth:1,
borderColor:colors.medium,
alignItems:'center',
width:'100%',
paddingHorizontal:10,
}
})
I have a header where is a input field. Is that possible to pass the value to my screen file ?
Header.js
import React, { useCallback } from 'react';
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View, TouchableOpacity, Dimensions, Platform, TextInput } from 'react-native';
import { useNavigation } from '#react-navigation/native';
import { Feather, AntDesign } from '#expo/vector-icons';
import Constants from 'expo-constants';
const width = Dimensions.get('window').width;
const headerHeight = 50;
const headerMessages = (text) => {
const navigation = useNavigation();
const [search, setSearch] = React.useState('');
const handleChangeInput = React.useCallback((e) => text(e));
const handleGoBack = useCallback(() => {
navigation.goBack();
});
return (
<View style={styles.container}>
<View style={styles.topHeader}>
<StatusBar color="#333" />
<Text style={styles.headerTitle}>Messages (0)</Text>
</View>
<View style={styles.searchContainer}>
<TextInput value={search} style={styles.searchInput} onChangeText={handleChangeInput} placeholder='Search Field' />
</View>
</View>
)
};
})
export default headerMessages;
Message.js
import * as React from 'react';
import { StyleSheet, Text, View, Pressable } from 'react-native';
const Messages = (props) => {
console.log(props.text);
return (
<View style={s.container}>
<Text>Messages</Text>
</View>
)
};
............................................................................................................................................................
If you want the 'search' state value in Message.js file, in that case initialize search in Message.js file and pass the setSearch hook as a callback function in the Header.js file.
And in the Header.js, get the state as props and set the value in textinput. In this way you will get the search value in the message.js file.
Why I get this error ?
TypeError: null is not an object (evaluating 'modalSuccess.open')
code:
import React, { useEffect, useState, useRef } from 'react';
import { StyleSheet, Text, View, TouchableOpacity, Image, ImageBackground } from 'react-native';
import { useNavigation } from '#react-navigation/native';
import { StatusBar } from 'expo-status-bar';
import Toast from 'react-native-toast-message';
import { updateVerified, toastShown } from '../redux/slice/authSlice';
import { useDispatch, useSelector } from 'react-redux';
import { Portal } from 'react-native-portalize';
import { ModalCollectionSuccess } from '../components/modal/successCollection/ModalCollectionSuccess';
const Profile = () => {
const navigation = useNavigation();
const dispatch = useDispatch();
const user = useSelector(state => state.user);
let modalSuccess = useRef(null).current;
const handleNavigateToAuthRegister = isUser => {
navigation.navigate('AuthRegister', {
isUser
});
};
const handleSetToastToFalse = () => {
Toast.hide();
dispatch(toastShown({user}))
};
useEffect(() => {
user.showCollectionSuccess === true && modalSuccess.open();
}, [user.showCollectionSuccess]);
return (
<View style={{flex: 1}}>
<StatusBar color="#fff" />
<Toast style={{position: 'absolute', zIndex: 2}} ref={(ref) => Toast.setRef(ref)} />
<Portal>
<ModalCollectionSuccess ref={el => (modalSuccess = el)} />
</Portal>
</View>
)
};
export default Profile;
....................................................................................................................................................................................................