Passing input text back to parent from component - reactjs

I am using an auto expanding text input field (Link) and I am creating it as a component. My question is when the text is changed how do I pass the value of the data back to the parent? I want to be able to submit the input via the parent so I was thinking of storing the input value in the parents state.
Parent
Calling the child component by using <InputExpand />
render() {
const { navigate } = this.props.navigation;
console.log("Rendering");
return (
<KeyboardAvoidingView behavior="padding" style={{flex: 1}}>
<View style={{flex: 1}}>
<StatusBar hidden={true} />
<View style={styles.headerBar}>
<NavBar navigation={this.props.navigation} goBack={this.goBack} title="MESSAGE DETAILS" backButton={true} showNewMessage={true} />
</View>
<View style={styles.contentWrapper}>
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow}
enableEmptySections={true}
style={styles.listWrapper}
/>
</View>
<View style={styles.footerBar}>
<View style={styles.footerBtnContainer}></View>
<View style={styles.footerInputContainer}>
<InputExpand />
</View>
<View style={styles.footerBtnContainer}>
<Image source={require('../../images/icons/IconSend.png')} style={{width: 20, height: 20}}/>
</View>
</View>
</View>
</KeyboardAvoidingView>
);
}
Component - (Child)
import React, { Component } from 'react'
const {
TextInput,
StyleSheet,
} = require('react-native');
export default class AutoExpandingTextInput extends React.Component {
state: any;
constructor(props) {
super(props);
this.state = {text: '', height: 0};
}
render() {
return (
<TextInput
{...this.props}
multiline={true}
onChange={(event) => {
this.setState({
text: event.nativeEvent.text,
height: event.nativeEvent.contentSize.height,
});
}}
style={[styles.default, {height: Math.max(35, this.state.height)}]}
value={this.state.text}
placeholder={"Type a message..."}
placeholderTextColor={"#fff"}
/>
);
}
}
var styles = StyleSheet.create({
default: {
color: "#fff",
fontSize: 10,
fontFamily: "Avenir-Light",
},
});

Yes, that is exactly what you should do. You create a handler in the parent state and pass it into the child component as a prop.
// parent component
// assuming a property inputText exists in the state
// and use arrow function to preserve the context of `this` to be of the parent class.
onChangeTextHandler = (e) => {
this.setState({
// get the value from TextInput onChangeText event
inputText: e.value,
})
}
render() {
const { navigate } = this.props.navigation;
console.log("Rendering");
return (
<KeyboardAvoidingView behavior="padding" style={{flex: 1}}>
<View style={{flex: 1}}>
<StatusBar hidden={true} />
<View style={styles.headerBar}>
<NavBar navigation={this.props.navigation} goBack={this.goBack} title="MESSAGE DETAILS" backButton={true} showNewMessage={true} />
</View>
<View style={styles.contentWrapper}>
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow}
enableEmptySections={true}
style={styles.listWrapper}
/>
</View>
<View style={styles.footerBar}>
<View style={styles.footerBtnContainer}></View>
<View style={styles.footerInputContainer}>
<InputExpand onChangeTextHandler= {this.onChangeTextHandler}/>
</View>
<View style={styles.footerBtnContainer}>
<Image source={require('../../images/icons/IconSend.png')} style={{width: 20, height: 20}}/>
</View>
</View>
</View>
</KeyboardAvoidingView>
);
}
// Child Component
import React, { Component } from 'react'
const {
TextInput,
StyleSheet,
} = require('react-native');
export default class AutoExpandingTextInput extends React.Component {
state: any;
constructor(props) {
super(props);
this.state = {text: '', height: 0};
}
render() {
const { onChangeTextHandler } = this.props;
return (
<TextInput
{...this.props}
multiline={true}
onChange={(event) => {
// set the state of parent component here...
onChangeTextHandler(event.nativeEvent.text);
this.setState({
text: event.nativeEvent.text,
height: event.nativeEvent.contentSize.height,
});
}}
style={[styles.default, {height: Math.max(35, this.state.height)}]}
value={this.state.text}
placeholder={"Type a message..."}
placeholderTextColor={"#fff"}
/>
);
}
}
var styles = StyleSheet.create({
default: {
color: "#fff",
fontSize: 10,
fontFamily: "Avenir-Light",
},
});
reactjs react-native

You should pass via props a callback for handle input text changes to the component, and use the onChange event of the input text to call that handle from the child component. If the input text doesn't have onChange (or something like that) you could use a onKeyUp. But the general idea is that you send a callback via props from the parent to the child, and you call it from the child to send data to the parent.

Related

Preventing state item in all components from changing with useContext()?

I'm trying to control the state of 2 components use useContext() in React-Native. I have a flatmap of cards that render on a screen. Each card has a press-able 'interested' icon. If I click on a card, it shows the details of the card and also the press-able 'interested' icon. Both should share the same state of being pressed and also send a 'interested bool to the backend.
Right now, if I press 'interested' on one card, the all get pressed. Same with the inside icon of the details page. Obviously the 'interested' state in the Context Provider is to broad and changing all of them. How can I filter out the state change?
Here is the card component that gets rendered from a flatlist:
import React, { useState, useEffect, useContext } from 'react';
import { Image, View, Text, TouchableOpacity } from 'react-native';
import { localDate } from 'utils/formatDate';
import PropTypes from 'prop-types';
import { ConcertContext } from '../../../context/ConcertContextProvider';
import LocationIcon from '../../../assets/images/locationIcon.svg';
import InterestedFilledIcon from '../../../assets/images/interested-filled.svg';
import InterestedEmptyIcon from '../../../assets/images/interested-empty.svg';
import ShareIcon from '../../../assets/images/share.svg';
import styles from './styles';
export default function ConcertCard({
gotoConcertPage,
artist,
cover,
concertCity,
scheduledAt,
description,
concertObj,
}) {
const [clickInterest, setClickInterest] = useState(concertObj.is_interested);
const { interested, setInterested, concertInterest } = useContext(ConcertContext);
const handleInterest = () => {
setInterested(prevState => !prevState);
concertInterest(concertObj);
};
useEffect(() => {
setClickInterest(interested);
}, [interested]);
return (
<TouchableOpacity onPress={() => gotoConcertPage(concertObj)}>
<View style={styles.card}>
<View style={styles.cardContent}>
<View style={styles.cropped}>
<Image style={styles.image} source={{ url: cover.url }} />
</View>
<View style={styles.textWrapper}>
<Text style={styles.date}>{localDate(scheduledAt, 'MMM D, h:mm A z')}</Text>
<View style={styles.locationWrapper}>
<LocationIcon style={styles.locationIcon} />
<Text style={styles.location}>{concertCity.name}</Text>
<Text style={styles.location}>{concertCity.address}</Text>
</View>
<Text style={styles.name}>{artist.name}</Text>
<Text style={styles.description}>{description}</Text>
</View>
<View style={styles.border} />
</View>
<View style={styles.icons}>
<View style={styles.sharedIcon}>
<ShareIcon />
</View>
{!clickInterest ? (
<InterestedEmptyIcon onPress={handleInterest} />
) : (
<InterestedFilledIcon onPress={handleInterest} />
)}
</View>
</View>
</TouchableOpacity>
);
}
ConcertCard.propTypes = {
gotoConcertPage: PropTypes.func,
artist: PropTypes.object,
cover: PropTypes.object,
concertCity: PropTypes.object,
scheduledAt: PropTypes.string,
description: PropTypes.string,
concertObj: PropTypes.object,
};
Here is the card details page:
import React, { useState, useEffect, useContext } from 'react';
import { Text, View, Image, ImageBackground, ScrollView, FlatList } from 'react-native';
import PropTypes from 'prop-types';
import Button from 'components/button';
import { localDate } from 'utils/formatDate';
import { ConcertContext } from '../../context/ConcertContextProvider';
import LocationIcon from '../../assets/images/locationIconTwo.svg';
import LittleFriendIcon from '../../assets/images/little-friend.svg';
import Star from '../../assets/images/Star.svg';
import QuestionMarkIcon from '../../assets/images/question-mark.svg';
import ShareIcon from '../../assets/images/ShareIconLarge.svg';
import styles from './concertStyles';
export default function ConcertPageScreen({ navigation, route }) {
const {
concertObj,
name,
artist,
scheduled_at,
interests,
concert_city,
other_cities,
description,
ticket_base_price,
} = route.params;
const { interested, setInterested, concertInterest } = useContext(ConcertContext);
const formatLocation = city => {
return city.slice(0, city.length - 5);
};
const handleInterest = () => {
setInterested(prevState => !prevState);
concertInterest(concertObj);
};
const buyTicket = concertObj => {
console.log('Buy ticked: ', concertObj.id);
};
return (
<>
<View style={styles.wrapper}>
<ImageBackground
style={styles.imageBackground}
imageStyle={{ opacity: 0.3 }}
source={{ url: artist.media }}
/>
<ScrollView vertical>
<View style={styles.headerWrapper}>
<Text style={styles.headerTitle}>{name}</Text>
<Text style={styles.smallText}>{artist.name}</Text>
<Text style={styles.date}>{localDate(scheduled_at, 'MMM D, h:mm A z')}</Text>
<View style={styles.locationWrapper}>
<LocationIcon style={styles.locationIcon} />
<Text style={styles.location}>{concert_city.name}</Text>
<Text style={styles.location}>{concert_city.address}</Text>
</View>
<Text style={styles.description}>{description}</Text>
<View style={styles.interestedWrapper}>
<LittleFriendIcon style={styles.littleMan} />
<Text style={styles.interested}>{interests} Interested</Text>
</View>
<View
style={{
borderTopColor: '#DADADA',
borderTopWidth: 0.2,
borderStyle: 'solid',
alignSelf: 'center',
height: 5,
marginTop: 32,
marginBottom: 28.5,
}}
/>
<View style={styles.tableWrapper}>
<View style={styles.tableHeaderWrapper}>
<Text style={styles.headerTitle}>DATES</Text>
<Text style={styles.headerTitle}>LOCATIONS</Text>
</View>
<View>
<FlatList
data={other_cities}
initialNumToRender={1}
renderItem={({ item }) => (
<View style={styles.tableItemsWrapper}>
<Text style={styles.dateItem}>
{localDate(item.date, 'MMM DD - h:mm A z')}
</Text>
<Text style={styles.locationItem}>{formatLocation(item.city)}</Text>
</View>
)}
concertCityId={item => `item${item.concert_city_id}`}
concertScheduleId={item => `item${item.concert_schedule_id}`}
/>
</View>
</View>
<View style={styles.iconWrapper}>
<View style={{ backgroundColor: '#292929', width: 44, height: 44, borderRadius: 30 }}>
<ShareIcon style={styles.shareIcon} />
</View>
{!interested ? (
<View
style={{ backgroundColor: '#292929', width: 44, height: 44, borderRadius: 30 }}>
<Star style={styles.starIcon} onPress={handleInterest} />
</View>
) : (
<View
style={{ backgroundColor: '#007AFF', width: 44, height: 44, borderRadius: 30 }}>
<Star style={styles.starIcon} onPress={handleInterest} />
</View>
)}
<Image style={styles.roundAvatar} source={{ url: artist.media }} />
</View>
<View style={styles.iconWrapper}>
<Text style={styles.shareIconText}>Share</Text>
<Text style={styles.interestedIconText}>I'm Interested</Text>
<Text style={styles.artistIconText}>Add Artist</Text>
</View>
<View style={styles.ticketWrapper}>
<Text style={styles.ticketPrice}>TICKET PRICES</Text>
<QuestionMarkIcon style={styles.ticketPrice} />
</View>
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
<Text style={styles.ticketLocation}>In-location</Text>
<Text style={styles.ticketLocation}>$ {ticket_base_price}</Text>
</View>
<View
style={{
borderTopColor: '#DADADA',
borderTopWidth: 0.5,
borderStyle: 'solid',
height: 20,
marginTop: 32,
marginBottom: 28.5,
}}
/>
<View style={styles.footerWrapper}>
<Text style={styles.headerTitle}>TICKET GUIDE</Text>
<Text style={styles.ticketDescription}>
This ticket is for a livestream concert. Sign In at www.colortv.me on your browser
to watch on our TV or laptop. On the go? Watch from the COLOR TV mobile app.
</Text>
</View>
</View>
<Button
rightIcon={false}
text="Buy Ticket"
style={styles.button}
onPress={() => buyTicket(concertObj)}
/>
</ScrollView>
</View>
</>
);
}
ConcertPageScreen.propTypes = {
navigation: PropTypes.object,
route: PropTypes.object,
};
and here is the Context Provider:
import React, { createContext, useState } from 'react';
import { concertInterestApi } from 'utils/apiRoutes';
import useFetcher from 'hooks/useFetcher';
import parseError from '../utils/parseError';
export const ConcertContext = createContext(null);
const ConcertContextProvider = ({ children }) => {
const { isLoading, error, fetcher } = useFetcher();
const [interested, setInterested] = useState([]);
const concertInterest = async concertObj => {
try {
await fetcher({
url: concertInterestApi(concertObj.id),
method: concertObj.is_interested ? 'DELETE' : 'POST',
});
} catch ({ response }) {
throw parseError(response);
}
};
return (
<ConcertContext.Provider value={{ interested, setInterested, concertInterest }}>
{children}
</ConcertContext.Provider>
);
};
export default ConcertContextProvider;
Perhaps I'm not wiring this up correctly at all and any suggestions would be welcome to manage state.
You are confused about the shape of your own context. In your Provider, interested is an array (I'm not sure of what) and setInterested is a function to replace that array. With that in mind, hopefully you can see the problem with this:
const { interested, setInterested, concertInterest } = useContext(ConcertContext);
const handleInterest = () => {
setInterested(prevState => !prevState);
concertInterest(concertObj);
};
You are treating interested as a boolean when it is an array. I think it's all of the concerts that this user is interested it? Or perhaps an array of all userIds who are interested in this concert? Or perhaps useState([]) is a mistake and it was always meant to be a boolean?
Either way, I would recommend moving the shared logic from the ConcertCard and ConcertPageScreen into a custom hook that consumes your context and return an onClickInterested handler function. Your hook can take the concert id and/or user id as an argument.

React Native child component not rendering on onPress event

I am trying to render the child component on onPressevent, the console.log works fine but components in the return function doesn't works.
Parent component:
onPress = (img,title,content) => {
this.setState({
show:true,
img:img,
title:title,
content:content
})
render() {
return (
<View style={styles.container}>
<FlatList
data={this.state.data}
renderItem={({item}) => (
<TouchableOpacity
onPress={() => this.onPress(item.urlToImage,item.title,item.content)}
>
<View style={styles.picsCont}>
<Image style={styles.pics} source={{uri: item.urlToImage}}/>
<Text style={{color:'white', fontSize: 15, fontWeight: '700', paddingTop:10}}>
{item.title}
</Text>
</View>
</TouchableOpacity>
)}
keyExtractor={item => item.title}
/>
{this.state.show ?
<NewsView
img={this.state.img}
title={this.state.title}
content={this.state.content}
/> :
null
}
</View>
);
}
}
Child Component:
export default class NewsView extends Component {
render() {
console.log(this.props.img)
return (
<View style={styles.container}>
<Image style={styles.picsCont} source={{uri:this.props.img}} />
<Text style={styles.news}>{this.props.title}</Text>
<Text style={styles.news}>{this.props.content}</Text>
</View>
)
}
}
Thanks for the help...!
It might be the styles. If your child component has position:'absolute', it´s probably under your parent component, you can try to put on your child component view zIndex:10

How to store the parent's props in child component?

I am studying React Naive by making a ToDo list.
I want to change the ToDo app to a Comment List that has comment one to another.
First attempt worked correctly:
First attempt
But, all users changed after second attempt.
Second attempt
Now, parent passes props to child by using {this.state.pick} and {this.state.key} , but child would change if parent's props changed.
Is there any way to change the parent props without changing child props?
Comment.js:
export default class CommentIndex extends Component<{}> {
constructor(props) {
super(props);
this.state = {
head: [],
list: [],
pick: [],
};
}
_onPress = (text) => {
const list = [].concat(this.state.list);
list.push({
key: Date.now(),
text: text,
done: false,
});
this.setState({
list,
});
}
render() {
const {
head,
list,
pick,
} = this.state;
var data = [["User1", "User2", "User3"],];
return (
<View style={styles.container}>
<View style={styles.dropdownHeader}>
<View style={styles.dropdown}>
<DropdownMenu
style={{flex: 1}}
bgColor={'white'}
tintColor={'#666666'}
activityTintColor={'green'}
handler={(selection, row) => this.setState({head: data[selection][row]})}
data={data}
>
<View style={styles.userHeader}>
{ this.state.head === 'User1' && <User1 /> }
{ this.state.head === 'User2' && <User2 /> }
{ this.state.head === 'User3' && <User3 /> }
</View>
</DropdownMenu>
</View>
</View>
<Text>To Do</Text>
<View style={styles.main}>
<View style={styles.post}>
<View style={styles.dropdown}>
<View style={{height: 0}} />
<DropdownMenu
bgColor={'white'}
tintColor={'#666666'}
activityTintColor={'green'}
handler={(selection,row) => this.setState({pick: data[selection][row]})}
data={data}
>
<View style={styles.user}>
{ this.state.pick === 'User1' && <User1_photo /> }
{ this.state.pick === 'User2' && <User2_photo /> }
{ this.state.pick === 'User3' && <User3_photo /> }
</View>
</DropdownMenu>
</View>
<View style={styles.postinput}>
<CommentInput onPress={this._onPress} />
</View>
</View>
<View style={styles.CommentListContainer}>
<FlatList
style={styles.CommentList}
data={list}
renderItem={({ item }) => <CommentItem {...item} head={this.state.head} pick={this.state.pick}/>}
/>
</View>
</View>
</View>
);
}
}
CommentInput:
export default class CommentInput extends Component {
constructor(props) {
super(props);
this.ref = {};
}
_onPress = () => {
this.props.onPress(this.ref._lastNativeText);
this.ref.setNativeProps({ text: '' });
}
render() {
const {
onPress,
} = this.props;
return (
<View style={styles.container}>
<TextInput
style={styles.textInput}
ref={(ref) => { this.ref = ref; }}
/>
<TouchableOpacity
style={styles.button}
onPress={this._onPress}
>
<Text style={styles.buttonText}>追加</Text>
</TouchableOpacity>
</View>
);
}
}
You could implement the shouldComponentUpdate method on the child. This will block a re-render (with the new properties) when you want.

How can I update text of dynamic component on react native?

I´m new to react and react-native, I want to show a component that is composed of:
so when the user checks the corresponding checkbox I transform the mentioned component adding another view getting something like this:
The problem comes when the user clicks on the Text element because I show a modal to pick the desired hour and minutes and when this modal closes I'm pretending to update the state and this updates the Text element with the selected time but it´s not working, any advice?
this is my code:
import React from 'react';
import {View,Text, TextInput, StyleSheet,TouchableOpacity} from 'react-native';
import { CheckBox } from 'react-native-elements';
import DateTimePicker from 'react-native-modal-datetime-picker';
let frmHoras;
export default class CustomChkHorario extends React.Component{
constructor(props){
super(props);
this.state={
chk:false,
fontColor:'black',
title:'Closed',
isDateTimePickerVisible: false,
sTimeMonday:'00:00',
eTimeMonday:'00:00'
}
}
_showDateTimePicker = () => {
this.setState({ isDateTimePickerVisible: true });
}
_hideDateTimePicker = () => this.setState({ isDateTimePickerVisible: false });
_handleDatePicked = (date) => {
console.log('A date has been picked: ', date);
this.setState({sTimeMonday:date});
this._hideDateTimePicker();
};
pressedChk = () => {
//console.log('checked:',this.state.checked);
this.setState({chk:!this.state.chk}, () =>{
if(this.state.chk==false){
this.setState({fontColor:'black', title:'Closed'});
frmHoras=null;
}else{
this.setState({fontColor:'green', title:'Open'});
frmHoras=
<View style={{flexDirection:'row',alignItems:'center'}}>
<Text>from:</Text>
<TouchableOpacity onPress={this._showDateTimePicker}>
<Text style={styles.input}>{this.state.sTimeMonday}</Text>
</TouchableOpacity>
<Text>to:</Text>
<TouchableOpacity onPress={this._showDateTimePicker}>
<Text style={styles.input}></Text>
</TouchableOpacity>
</View>;
}
});
}
render(){
return(
<View style={{alignItems:'center'}}>
<View style={{flexDirection:'row',justifyContent:'center',alignItems:'center'}}>
<Text>{this.props.dia}</Text>
<CheckBox title={this.state.title}
checked={this.state.chk}
onPress={this.pressedChk}
checkedColor='green'
textStyle={{color:this.state.fontColor}}></CheckBox>
</View>
<View>
{frmHoras}
</View>
<DateTimePicker
isVisible={this.state.isDateTimePickerVisible}
onConfirm={this._handleDatePicked}
onCancel={this._hideDateTimePicker}
mode={'time'}
/>
</View>
);
}
}
const styles = StyleSheet.create({
input: {
marginHorizontal: 10,
height:25,
width:60,
borderBottomColor:'black',
borderStyle:'solid',
borderBottomWidth:1,
margin:10
}
});
_handleDatePicked = date => {
const time = new Date(date);
const timePicked = `${time.getHours()}:${time.getMinutes()}`;
this.setState({ sTimeMonday: timePicked });
this._hideDateTimePicker();
};
pressedChk = () => {
this.setState({ chk: !this.state.chk }, () => {
if (this.state.chk) {
this.setState({ fontColor: 'green', title: 'Open' });
} else {
this.setState({ fontColor: 'black', title: 'Closed' });
}
});
};
render() {
return (
<View style={{ alignItems: 'center' }}>
<View
style={{
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
}}>
<Text>{this.props.dia}</Text>
<CheckBox
title={this.state.title}
checked={this.state.chk}
onPress={this.pressedChk}
checkedColor="green"
textStyle={{ color: this.state.fontColor }}
/>
</View>
{this.state.chk && (
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text>from:</Text>
<TouchableOpacity onPress={this._showDateTimePicker}>
<Text style={styles.input}>{this.state.sTimeMonday}</Text>
</TouchableOpacity>
<Text>to:</Text>
<TouchableOpacity onPress={this._showDateTimePicker}>
<Text style={styles.input} />
</TouchableOpacity>
</View>
)}
<DateTimePicker
isVisible={this.state.isDateTimePickerVisible}
onConfirm={this._handleDatePicked}
onCancel={this._hideDateTimePicker}
mode={'time'}
/>
</View>
);
}
}
You should render frmHoras in a function, but you are currently doing that in the setState callback, which is a bit misleading in your case, as setState callback is called when setState is completed and the component is re-rendered. Look at the document which clearly mentioned about this behaviour
The second parameter to setState() is an optional callback function that will be executed once setState is completed and the component is re-rendered.
So, changes will as follows
Create a new function which will render frmHoras, let it be renderFrmHoras
renderFrmHoras = () => {
const { chk } = this.state;
if(!chk) {
return null;
}
return (
<View style={{flexDirection:'row',alignItems:'center'}}>
<Text>from:</Text>
<TouchableOpacity onPress={this._showDateTimePicker}>
<Text style={styles.input}>{this.state.sTimeMonday}</Text>
</TouchableOpacity>
<Text>to:</Text>
<TouchableOpacity onPress={this._showDateTimePicker}>
<Text style={styles.input}></Text>
</TouchableOpacity>
</View>;
);
}
Next, update the pressedChk to set fontColor, title and chk values
pressedChk = () => {
this.setState((prevState) => {
return ({
chk: !prevState.chk,
fontColor: !prevState.chk ? 'green' : 'black',
title: !prevState.chk ? 'Open' : 'Closed'
});
})
}
Next, in the render method, just call the renderFrmHoras function
render() {
return (
...
</View>
<View>
{this.renderFrmHoras()}
</View>
<DateTimePicker
...
/>
...
);
}
Hope this will help!

Add data in React Native and Save the State

I'm building a basic React Native application where the user enters his name in a TextInput and on button press his name along with his image is added to a ScrollView in another View. Images are stored and named in accord with the name of the person. Example - Name: 'ABC', the image fetched from assets will be 'ABC.jpg'.
I'm able to do this for one person, but every time I add a new entry the previous one gets overwritten. How can I retain the previous entry yet add another entry?
Home
import React, {Component} from 'react';
import { StyleSheet, Text, View, Image, ScrollView, Button, TouchableWithoutFeedback, TextInput} from 'react-native';
import { createStackNavigator } from 'react-navigation';
class HomeScreen extends React.Component {
render() {
const { navigation } = this.props;
const name0 = navigation.getParam('name0', 'NO-ID');
return (
<View style={styles.container}>
<ScrollView vertical={true} contentContainerStyle={{flexGrow: 1}}>
<Text style={styles.category}>Category 1</Text>
<ScrollView horizontal={true} showsHorizontalScrollIndicator={false}>
<TouchableWithoutFeedback onPress={() => {
this.props.navigation.navigate('Details', {
name: name0,
intro: 'lorem ipsum',
detail1: 'XYZ',
detail2: 'ABC',
});
}}>
<View style={styles.view}>
<Image source={require('./assets/rohit.jpg')} style={styles.image}></Image>
<Text style={styles.text}>{name0}</Text>
</View>
</TouchableWithoutFeedback>
</ScrollView>
</ScrollView>
</View>
)
}
}
Add Data
class AddData extends React.Component {
constructor(props) {
super(props);
this.state = { text: '' };
}
render() {
function onPressLearnMore() {
alert('Hi')
}
return (
<View style={{flex: 1, flexDirection: 'column', justifyContent:'center', alignItems: 'center'}}>
<TextInput
style={{height: 40,width:200}}
onChangeText={(text) => this.setState({input: text})}
/>
<Button
onPress={() => {
this.props.navigation.navigate('Home', {
name0: this.state.input
});
}}
title="Pass Data"
/>
</View>
);
}
}
Navigator
const RootStack = createStackNavigator(
{
Home: HomeScreen,
Details: DetailsScreen,
Data: AddData
},
{
initialRouteName: 'Data',
}
);
export default class App extends React.Component {
render() {
return <RootStack />;
}
}
Screen 1
Screen 2
Because you aren't saving your data from the user input anywhere, simply passing it back to home, it is getting overwritten and as your code sits, it is working! ;)
To simply put a bandaid on what you're doing, because this method of passing data is slightly taboo.. and you cannot achieve what you're asking without some sort of state persistence like AsyncStorage, or... to not have two screens. Because everytime React re-renders your screen any data that was in your state object disappears...
Inside your home component, on did mount you could store user input to state as objects inside an array. IN the below example I am using the user data you are sending back to home, however this would need to be data retrieved from some sort of persistence.
class HomeScreen extends React.Component {
constructor(props) {
super(props)
this.state = {
usersArray: []
}
}
componentDidMount() {
let userInfo = this.props.navigation.getParam('name0', 'NO-ID');
userInfo !== undefined ? this.setState({usersArray:
[...this.state.usersArray, userInfo]}) : console.log('NO USER DATA to add')
}
render() {
const { navigation } = this.props;
const name0 = navigation.getParam('name0', 'NO-ID');
return (
<View style={styles.container}>
<ScrollView vertical={true} contentContainerStyle={{flexGrow: 1}}>
<Text style={styles.category}>Category 1</Text>
<ScrollView horizontal={true} showsHorizontalScrollIndicator={false}>
<TouchableWithoutFeedback onPress={() => {
this.props.navigation.navigate('Details', {
name: name0,
intro: 'lorem ipsum',
detail1: 'XYZ',
detail2: 'ABC',
});
}}>
<View style={styles.view}>
<Image source={require('./assets/rohit.jpg')} style={styles.image}></Image>
{/* <Text style={styles.text}>{name0}</Text> */}
{ this.state.usersArray.map((ele, index) => {
return <Text key={index} style={styles.text}>{ele.name}</Text>
})}
</View>
</TouchableWithoutFeedback>
</ScrollView>
</ScrollView>
</View>
)
}
}
Please keep in mind you may need to change your user data to be objects for this rest and spreading to work.

Resources