I'm trying to pass a param to a new screen in order to display it. my object is in a fetched data of array that i display using map, the code looks like this:
<Text > Show:</Text>
{
this.state.data.map((item, i) => {
//Show only two dates
return (i < 2) ?
<View>
<Text>{moment(item[0]).format("ddd DD/MM")}</Text>
<View style={{ flex: 1, flexDirection: 'row' }}>
{
item[1].map((day, i) => {
//show only 3 times
return (i < 3) ?
<TouchableOpacity onPress={() => NavigationService.navigate('myScreen',//what should i wright here!>
<Text>{moment(day.date_start).format("h:mm a")}</Text> // i want to pass this displayed text {moment(day.date_start).format("h:mm a")}
</TouchableOpacity>
:
<></>
})
}
</View>
</View>
: <></>
})
}
so as you can see i want to pass {moment(day.date_start).format("h:mm a")} to myScreen and display it, but i can't figure out how.
myScreen code is simple:
class Myscreen extends React.Component {
render() {
return (
<Text> display it here! </Text>
i would appreciate some help.thank you
In your first screen, you have to pass the text like this...
<TouchableOpacity onPress={() => this.props.navigation.navigate('myScreen', { text: moment(day.date_start).format("h:mm a") })}>
<Text>Press me</Text>
</TouchableOpacity>
In your myScreen, you have to receive it like this...
class Myscreen extends React.Component {
constructor(props) {
super(props);
}
render() {
const text = this.props.route.params.text;
return (
<Text>{text}</Text>
)
}
}
Please make sure that you are using #react-navigation/stack": "^5.x.x
Related
I'm learning React Native for the first time. I want to implement a function to show/hide the component by touching the screen, not a specific button.
(Please check the attached file for the example image.)
enter image description here
In this code, I've tried to make a function. if I touch the screen (<View style={style.center}>, then show/hide the renderChatGroup() and renderListMessages() included in <View style={style.footer}>. The source code is below.
In my code, it works. However, the two <View> tag is not parallel. the footer view is center View's child.
I want to make them parallel. but I couldn't find the contents about controlling another <View> tag, not a child. In this code, I used setState, then I couldn't control another the below <View>.
Of course, I tried Fragment tag, but it didn't render anything.
How could I do implement this function? Please help me!
export default class Streamer extends React.Component {
constructor(props) {
super(props);
this.state = {
isVisibleFooter: true,
};
}
renderChatGroup = () => {
const { isVisibleFooter } = this.state;
if (isVisibleFooter) {
return (
<ChatInputGroup
onPressHeart={this.onPressHeart}
onPressSend={this.onPressSend}
onFocus={this.onFocusChatGroup}
onEndEditing={this.onEndEditing}
/>
);
}
return null;
};
onPressVisible = () => {
const { isVisibleFooter } = this.state;
this.setState(() => ({ isVisibleFooter: !isVisibleFooter }));
};
render() {
return (
<SafeAreaView style={styles.container}>
<SafeAreaView style={styles.contentWrapper}>
<View style={styles.header} />
<TouchableWithoutFeedback onPress={this.onPressVisible}>
<View style={styles.center}>
<View style={styles.footer}>
{this.renderChatGroup()}
{this.renderListMessages()}
</View>
</View>
</TouchableWithoutFeedback>
</SafeAreaView>
</SafeAreaView>
);
}
}
Firstly I would highly recommend you use react native with functional components and React Hooks as they alternative will soon will be deprecated.
Since onPress is not available on the View Component, you would need to replace it with TouchableWithoutFeedback as you have already done in your code.
For Showing/Hiding a view you would need to use a conditional operator.
export default class Streamer extends React.Component {
constructor(props) {
super(props);
this.state = {
isVisibleFooter: true,
};
}
renderChatGroup = () => {
const { isVisibleFooter } = this.state;
if (isVisibleFooter) {
return (
<ChatInputGroup
onPressHeart={this.onPressHeart}
onPressSend={this.onPressSend}
onFocus={this.onFocusChatGroup}
onEndEditing={this.onEndEditing}
/>
);
}
return null;
};
onPressVisible = () => {
this.setState(() => ({ isVisibleFooter: !isVisibleFooter }));
const { isVisibleFooter } = this.state;
};
render() {
return (
<SafeAreaView style={styles.container}>
<SafeAreaView style={styles.contentWrapper}>
<View style={styles.header} />
<TouchableWithoutFeedback onPress={this.onPressVisible}>
<View style={styles.center}>
{isVisibleFooter && <View style={styles.footer}>
{this.renderChatGroup()}
{this.renderListMessages()}
</View>}
</View>
</TouchableWithoutFeedback>
</SafeAreaView>
</SafeAreaView>
);
}
}
Here you can see i have replaced
<View style={styles.footer}>
{this.renderChatGroup()}
{this.renderListMessages()}
</View>
with
{isFooterVisible && <View style={styles.footer}>
{this.renderChatGroup()}
{this.renderListMessages()}
</View>}
stating that to only display the Footer View when
const isFooterVisible = true;
I am using TouchableOpacity from react-native. The code is:
<TouchableOpacity onPress={onPress}>
<Text style={styles.supplementItem}>{item.item}</Text>
</TouchableOpacity>
where the OnPress function is as:
const onPress = () => (
// eslint-disable-next-line no-sequences
<Text style={styles.supplementItem}>Hello</Text>
this.setState({tempKey: tempKey + 1})
);
I looked at: this question and tried to do like it. But this is not working. I am setting my states as follows:
constructor(props) {
super(props);
this.state = {
tempKey: 0,
};
}
Kindly help me what I am doing wrong.
The question which you mentioned is using function based components and you are using class based components as you showed the costructor part which proves that.
So onPress must be a method in that class in your case, so you don't need the const keyword before it and you need to call it in this way ; this.onPress
In nutshell, your whole component should be like this;
import React from 'react';
import {Text, TouchableOpacity, View} from 'react-native';
class YourComp extends React.Component {
constructor(props) {
super(props);
this.state = {
tempKey: 0,
show: false
};
}
onPress = () => {
// eslint-disable-next-line no-sequences
this.setState(prevState => ({tempKey: prevState.tempKey + 1}))
};
render() {
return (
<View>
<TouchableOpacity style={{height: 100, justifyContent: 'center', alignItems: 'center'}} onPress={() => this.onPress()}>
<Text>Hello (item.item in your case)</Text>
</TouchableOpacity>
<Text key={this.state.tempKey.toString()}>Hello {this.state.tempKey}</Text>
</View>
)
}
}
export default YourComp;
If you want to show some component conditionally;
this.state = {
...,
show: false
}
Then in the onPress method;
this.setState(prevState => ({show: !prevState.show})) // this will make <Text /> to toggle the modal when clicked.
Then in the render method;
<Text>
{this.state.show && (
<YourNewComponent />
) || null}
</Text>
This is screen 1, where I am supposed to be passing the state for button text.
export class EditProfile extends Component {
constructor(props) {
super(props);
this.navigateToName = this.navigateToName.bind(this);
this.navigateToAboutMe = this.navigateToAboutMe.bind(this);
this.navigateToInterests = this.navigateToInterests.bind(this);
this.state = {
showing: true,
aboutUser: {
buttonText: "hey",
showing: false,
},
};
}
navigateToName = () => {
this.props.navigation.navigate("CreateProfile", {
showing: false,
});
};
navigateToAboutMe = () => {
this.props.navigation.navigate("AboutUser", {
aboutUser: this.state.aboutUser,
});
};
navigateToInterests = () => {
this.props.navigation.navigate("Interests", { showing: false });
};
render() {
return (
<View>
<View style={ProfileEditStyle.justifyImage}>
<Image
style={ProfileEditStyle.image}
source={require("../../Graphics/jessica_alba.jpg")}
/>
</View>
<View>
<Text style={ProfileEditStyle.basictext}>Basic Info</Text>
<TouchableOpacity style={ProfileEditStyle.buttons}>
<Text style={ProfileEditStyle.text} onPress={this.navigateToName}>
Edit Name
</Text>
</TouchableOpacity>
<TouchableOpacity style={ProfileEditStyle.buttons}>
<Text style={ProfileEditStyle.text}>Edit Photo</Text>
</TouchableOpacity>
<TouchableOpacity style={ProfileEditStyle.buttons}>
<Text style={ProfileEditStyle.text}>Edit Location</Text>
</TouchableOpacity>
<TouchableOpacity
style={ProfileEditStyle.buttons}
onPress={this.navigateToAboutMe}
>
<Text style={ProfileEditStyle.text}>Edit About Me</Text>
</TouchableOpacity>
<TouchableOpacity
style={ProfileEditStyle.buttons}
onPress={this.navigateToInterests}
>
<Text style={ProfileEditStyle.text}>Edit Interests</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
export default EditProfile;
This is screen 2, where I want the state for the buttonText to change on the continue button component.
export class AboutUser extends Component {
constructor(props) {
super(props);
this.navigatToInterests = this.navigatToInterests.bind(this);
this.checkEntry = this.checkEntry.bind(this);
var params = props.navigation.state.params.aboutUser;
this.state = {
value: "",
};
}
<ContinueButton
text={this.props.route.params.aboutUser.buttonText}
color="#ff304f"
style={CreateAboutMe.centerButton}
onPress={this.navigatToInterests}
/>
I am trying to do conditional rendering for the continue button component. When its on one screen I want it to say "continue" and when its on another route I want it to say " Save and Go Back". However when I try to change the state between screens for some reason I either get a params error or the state doesn't change.
Get parameter from previous screen :
constructor(){
const isShowBtn = this.props.navigation.getParam("showing");
this.state = {
value: isShowBtn
}
}
I have an 'OutputBox' component and want to change the text being displayed in the component when I click a button.
I've read about props and state and i can't seem to get them working the way i need them too. I just started react-native and have a heavy background c++. I thought i could just declare a variable, 'text' in the 'OutputBox' component and then call a 'setOutputBoxText' function and change the 'text' var. Getters and Setters paradigm. I just cant wrap my head around how to use props to 'pass args' to components and the such.
export default class HelloWorldApp extends Component {
render() {
return (
<View style={{ flex: 1, alignItems: "flex-end" }}>
<CustomButton
text="N"
onPress={() => {
OutputBox.setOutputBox('You head North');
alert("You head North");
}}
/>
<OutputBox></OutputBox>
</View>
);
}
}
class CustomButton extends Component {
render() {
const { text, onPress} = this.props;
return (
<TouchableOpacity style={styles.buttonStyle}
onPress={() => onPress()}
>
<Text style={styles.textStyle}>{text}</Text>
</TouchableOpacity>
);
}
}
class OutputBox extends Component {
constructor( props ) {
super( props );
var displayText = 'Hello Traveller';
}
setOutputBox( newText ){
displayText = newText;
}
render() {
return (
<View style={ styles.outputBox }>
<Text>{this.displayText}</Text>
</View>
);
}
}
I would expect to be able to do something similar to what i have, however i just keep getting a typeError: OutputBox.setOutputBox is not a function. I know this is the wrong paradigm for react-native. I can't seem to wrap my head around doing something like this with props and state.
UPDATE: I no longer get the error typeError: OutputBox.setOutputBox is not a function. Now, the OutputBox just doesn't display anything. How I do I get the <Text/> component of the OutputBox to change and display.
Here is the correct way to do it.
export default class HelloWorldApp extends Component {
constructor( props ) {
super( props );
this.state={
displayText : 'Hello Traveller',
}
}
render() {
return (
<View style={{ flex: 1, alignItems: "flex-end" }}>
<CustomButton
text="N"
onPress={() => {
this.setState({displayText:'You head North'})
}}
/>
<OutputBox text={this.state.displayText}/>
</View>
);
}
}
class CustomButton extends Component {
render() {
const { text, onPress} = this.props;
return (
<TouchableOpacity style={styles.buttonStyle}
onPress={() => onPress()}
>
<Text style={styles.textStyle}>{text}</Text>
</TouchableOpacity>
);
}
}
class OutputBox extends Component {
render() {
return (
<View style={ styles.outputBox }>
<Text>{this.props.displayText}</Text>
</View>
);
}
}
I just removed the OutputBox component and put a <Text> component in there. I realized i didn't need the OutputBox component, since it's only purpose was to display text. This is what i ended up with
export default class HelloWorldApp extends Component {
constructor( props ) {
super( props );
this.state={
displayText : 'Hello Traveller',
}
}
render() {
return (
<View style={{ flex: 1, alignItems: "flex-end" }}>
<CustomButton
text="N"
onPress={() => {
this.setState({displayText:'You head North'})
}}
/>
<Text>{this.state.displayText}</Text>
</View>
);
}
}
class CustomButton extends Component {
render() {
const { text, onPress} = this.props;
return (
<TouchableOpacity style={styles.buttonStyle}
onPress={() => onPress()}
>
<Text style={styles.textStyle}>{text}</Text>
</TouchableOpacity>
);
}
}
//Home page
class Home extends Component {
constructor(props){
super(props);
this.state = {time: ""}
}
render(){
const { navigate } = this.props.navigation;
return(
<View>
<TextInput onChangeText={(time) => this.setState({ time })} placeholder = "enter time" />
<TouchableOpacity style={{marginTop: 10, height: 20, width: 50, borderRadius: 6, borderColor: 'white', backgroundColor:'red'}}
onPress = { () => {
navigate('Wait', {
time: this.state.time * 1000
})
}}
>
<Text style={{color: 'white'}}>add</Text>
</TouchableOpacity>
</View>
)
}
}
//Waitlist page
class Wait extends Component{
constructor(props){
super(props);
this.state = { data: []}
}
renderTime(){
return this.state.data.map((item) => {
return(
<View>
<TimerCountdown
initialSecondsRemaining={ item }
allowFontScaling={true}
style={{ fontSize: 20 }}
/>
</View>
)
})
}
updatestate(time){
var temp = this.state.data
temp.push(time)
this.setState({data: temp})
}
render(){
const { navigate } = this.props.navigation;
const { navigation } = this.props;
const time = navigation.getParam('time', 'NO-Name');
return(
<View>
<TouchableOpacity onPress = {()=>{ this.updatestate(time)}}>
<Text> Update </Text>
</TouchableOpacity>
<View>
{this.renderTime()}
</View>
</View>
)
}
}
I am trying to write a function to keep adding countdown timer to another page. After the user enter the input time, it should navigate to the waitlist page and update the state and render all the timers. The above code does not work because each time I navigate to that page the state will reset.
I also tried it with the AsyncStorage. I was able to add the time to the AsyncStorage on the home page and render each time on the waitlist page. But the problem is all the timers will reset every time I add a new timer.
I just want to know how can I keep the previous state after navigate to another page. Can someone please show me some examples? Thanks a lot.
Documentation for timer-countdown: https://www.npmjs.com/package/react-native-timer-countdown