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.
Related
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
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,
}
})
While pressing RoundButton component nothing happens, but when I press press return it works,
Here is my custom Button component
Custom Button:
import React from 'react';
import { Text, View, StyleSheet, TouchableOpacity, } from 'react-native';
export const RoundedButton = ({
style = {},
textStyle = {},
size = 125,
...props
}) => {
return( <TouchableOpacity style={[styles(size).radius,style]}>
<Text style={[styles(size).text,textStyle]}>{props.title} </Text>
</TouchableOpacity>);
};
Calling from component:
import React, {useState} from 'react';
import { Text, View, StyleSheet,TouchableHighlight } from 'react-native';
import {TextInput} from "react-native-paper";
import {RoundedButton} from '../../components/RoundedButton'
export const Focus = ({addSubject}) => {
const [focusSubject, setFocusSubject] = useState(null);
const [tempItem, setTempItem] = useState(null);
return (
<View style={styles.container}>
<View style={styles.titleContainer}>
<Text>Want something?</Text>
<View styles={styles.inputContainer} >
<TextInput onSubmitEditing={({ nativeEvent }) => {
setTempItem(nativeEvent.text);
addSubject(nativeEvent.text)
}} />
<RoundedButton size={100} title="+" onPress={()=> {addSubject(tempItem)}} />
</View>
</View>
</View>
);
}
You need to call onPress on TouchableOpacity
Custom Button:
import React from 'react';
import { Text, View, StyleSheet, TouchableOpacity, } from 'react-native';
export const RoundedButton = ({
style = {},
textStyle = {},
size = 125,
...props
}) => {
return(
<TouchableOpacity onPress={props.onButtonHandler} style={[styles(size).radius,style]}>
<Text style={[styles(size).text,textStyle]}>{props.title} </Text>
</TouchableOpacity>
)};
In your component pass onButtonHandler
Calling from component:
import React, {useState} from 'react';
import { Text, View, StyleSheet,TouchableHighlight } from 'react-native';
import {TextInput} from "react-native-paper";
import {RoundedButton} from '../../components/RoundedButton'
export const Focus = ({addSubject}) => {
const [focusSubject, setFocusSubject] = useState(null);
const [tempItem, setTempItem] = useState(null);
return (
<View style={styles.container}>
<View style={styles.titleContainer}>
<Text>Want something?</Text>
<View styles={styles.inputContainer} >
<TextInput onSubmitEditing={({ nativeEvent }) => {
setTempItem(nativeEvent.text);
addSubject(nativeEvent.text)
}} />
<RoundedButton size={100} title="+" onButtonHandler={()=> {addSubject(tempItem)}} />
</View>
</View>
</View>
);
}
I am creating a react native application and I have problem when I want to navigate between screens it gives error as " Cannot read property 'navigate' of Undefined " . I want when I press gear icon it must navigate to settings part . I couldn't clearly see where did I mistake .
settings button touchable opacity
import React from 'react';
import {createStackNavigator} from 'react-navigation-stack';
import { createAppContainer} from 'react-navigation';
import PS from '../screens/PS';
import SPC from '../screens/SPC';
import TFA from '../screens/2FA';
import Login from '../screens/Login';
import Settings from '../screens/settings';
const screens = {
Login: {
screen: Login,
navigationOptions: {
header: null,
}
},
TFA:{
screen: TFA
},
PS: {
screen: PS,
navigationOptions: {
header: null,
}
},
SPC: {
screen: SPC
},
Settings: {
screen: Settings
}
}
const HomeStack = createStackNavigator(screens);
export default createAppContainer(HomeStack);
import React, {useState}from 'react';
import SettingsButton from './SettingsButton';
import ConnectionIcon from './Connectionİcon';
import { View, Image, StyleSheet } from 'react-native';
const Header = () => {
return (
<View style={styles.header}>
<View style={styles.headerp1}></View>
<View style={styles.headerp2}><Image
source={require('../assets/images/monitor.png')}
/></View>
<View style={styles.headerp3}>
<SettingsButton />
<ConnectionIcon />
</View>
</View>
)
}
export default Header;
// const styles here
import React from 'react';
import { Image, TouchableOpacity, StyleSheet } from 'react-native';
const SettingsButton = ({ navigation }) => {
return (
<TouchableOpacity
style={styles.headerp3v2}
onPress={() => navigation.navigate('Settings')}
>
<Image style={styles.reddot}
source={require('../assets/images/gear.png')}
/>
</TouchableOpacity>
)
}
export default SettingsButton;
// const stlyes codes here
header file is here
import { Image, StyleSheet, Button, View, Text, SafeAreaView, StatusBar } from 'react-native';
import Footer from '../components/Footer';
import Header from '../components/Header';
import PV from '../components/PV';
export default function PS() {
return (
<View style={styles.container}>
<StatusBar hidden />
<Header />
<View><Text style={styles.text}>All Persons</Text></View>
<PV />
<Footer/>
</View>
);
}```
You don't pass navigation prop into SettingsButton
You can try use useNavigation hook https://reactnavigation.org/docs/use-navigation/ for get navigation object into SettingsButton
import React from 'react';
import { Image, TouchableOpacity, StyleSheet } from 'react-native';
import { useNavigation } from '#react-navigation/native'; // <-- new code
const SettingsButton = () => {
const navigation = useNavigation(); // <-- new code
return (
<TouchableOpacity
style={styles.headerp3v2}
onPress={() => navigation.navigate('Settings')}
>
<Image style={styles.reddot}
source={require('../assets/images/gear.png')}
/>
</TouchableOpacity>
)
}
export default SettingsButton;
I am wondering how I can dispatch an action from n-th level nested components. This is wha I have got:
BodyContainer (contains connect, mapProps, mapDispatch, etc.) => Body
=Body (Component) where the actions are dispatched)
==Grid (Component)- state is passed as props from Body and some elements parts of the state are further passed on to the next component as props.
===Square (Component) - receives some part of the state as props.
Now, I'd like to dispatch an action from the Square component to change the state. I thought I'll just do a SquareContainer first but then how would it get the parts of the state from Grid?
See below the components (let me know if you need more information):
BodyContainer:
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { listNumbers, pickNumber } from '../actions/numberActions';
import { populateRow, populateGrid } from '../actions/gridActions';
import Body from '../components/Body';
const mapStateToProps = state => ({
numbers: state.numbers,
grid: state.grid
});
const mapDispatchToProps = dispatch => (
bindActionCreators({
listNumbers,
pickNumber,
populateRow,
populateGrid
}, dispatch)
);
export default connect(
mapStateToProps,
mapDispatchToProps
)(Body);
Body Component
import React, { Component, PropTypes } from 'react';
import { View, StyleSheet, Button } from 'react-native';
import Grid from './Grid';
import * as globalStyles from '../styles/global';
export default class Body extends Component {
componentWillMount() {
this.refresh();
}
refresh() {
this.props.populateGrid();
}
render() {
return (
<View style={styles.body}>
<Grid inGrid={this.props.grid} />
<View style={styles.buttonContainer}>
<Button
onPress={this.refresh.bind(this)}
title={'Regenerate the Grid'}
/>
</View>
</View>
);
}
}
Grid component
import React, { Component, PropTypes } from 'react';
import { View, StyleSheet } from 'react-native';
import Square from './Square';
import * as globalStyles from '../styles/global';
export default class Grid extends Component {
render() {
const row = [];
let i = 0;
this.props.inGrid.forEach((r) => {
r.forEach((c) => {
i++;
row.push(
<Square key={i} sqValue={c} />
);
});
});
const { grid } = styles;
return (
<View style={grid}>
{row}
</View>
);
}
}
Square Component
import React, { PropTypes } from 'react';
import { View, Text, StyleSheet, TouchableHighlight } from 'react-native';
import * as globalStyles from '../styles/global';
const Square = ({ sqValue }) => {
const { square, textStyle, squareActive } = styles;
return (
<TouchableHighlight
style={[square, sqValue[1] && squareActive]}
onPress={() => console.log(sqValue[0])}
>
<View>
<Text style={textStyle}>{sqValue[0]},{sqValue[1]}</Text>
</View>
</TouchableHighlight>
);
};
Edit: I've changed the Square component to a stateful one:
import React, { Component, PropTypes } from 'react';
import { View, Text, StyleSheet, TouchableHighlight } from 'react-native';
import * as globalStyles from '../styles/global';
export default class Square extends Component {
render() {
const { square, textStyle, squareActive } = styles;
const { sqValue } = this.props;
return (
<TouchableHighlight
style={[square, sqValue[1] && squareActive]}
onPress={() => console.log(sqValue[0])}
>
<View>
<Text style={textStyle}>{sqValue[0]},{sqValue[1]}</Text>
</View>
</TouchableHighlight>
);
}
}
I'd like to dispatch an action from onPress={}. Thank you