How to pass state between screens in React Native - react-native

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
}
}

Related

How to use for Loop in react native

I am new to react native I want to use for loop for showing multiple data. which is come from previous screen from API.
here is my code. I want to show full view in return in for loop multiple times. I am getting data in this => this.props.route.params.data[i].lead_tag_number
const { width } = Dimensions.get("window");
class Browse extends Component {
constructor(props) {
super(props);
this.state ={
Email:"",
}
this.handleBackButtonClick = this.handleBackButtonClick.bind(this);
}
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButtonClick);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButtonClick);
}
handleBackButtonClick() {
this.props.navigation.navigate("Browse");
return true;
}
render() {
const { profile, navigation } = this.props;
const tabs = [""];
const route = this.props
return (
<View style={{alignItems:"center", justifyContent:"center",height:140, width:"90%", marginTop:30}}>
<TouchableOpacity onPress={() => navigation.navigate("FormItems")}>
<Card center middle shadow style={{ height:80, width:"100%" }} >
<Text medium height={15} size={14}style={{ fontWeight: "bold", paddingRight:190}}>
{this.props.route.params.data[i].lead_tag_number}
</Text>
</Card>
</TouchableOpacity>
</View>
);
}
}
Did you try this?
...
this.props.route.params.data[i].lead_tag_number.map((item, i){
<TAG key={i} />
});
...

change custom radio button image onclick

I'm trying to create a button that can change the image when it is clicked, I've tried with changing its opacity now I'm trying to change the image. Here's what I've done for the custom button
const styles = StyleSheet.create({
container: {
marginVertical: normalize(5),
opacity: 0.5
},
activeButton: {
opacity: 1
}
});
export default class RadioButton extends Component {
constructor(props) {
super(props);
this.state = {
selected: this.props.currentSelection === this.props.value,
}
}
componentDidUpdate(prevProps) {
if (this.props.currentSelection !== prevProps.currentSelection) {
this.setState({ selected: this.props.currentSelection === this.props.value });
}
}
render() {
let activeButton = this.props.activeStyle ? this.props.activeStyle : styles.activeButton;
return (
<View style={[styles.container, this.props.containerStyle, this.state.selected ? activeButton : null]}>
<TouchableOpacity onPress={() => {
this.setState({ selected: !this.state.selected });
this.props.onPress();
}}>
{
this.props.element ?
this.props.element :
<Text> {this.props.value} </Text>
}
</TouchableOpacity>
</View>
);
}
}
It should be like this image
First import both images. one for selected and another for normal state.
import selectedImg from '../images/selected.png';
import normalImg from '../images/normal.png';
and then add below method to your component
btnBackgroundImage() = {
var imgSource = this.state.selected? selectedImg : normalImg;
return (
<Image
style={'put style here'}
source={ imgSource }
/>
);
}
now edit your render method like below
render() {
let activeButton = this.props.activeStyle ? this.props.activeStyle : styles.activeButton;
return (
<View style={[styles.container, this.props.containerStyle, this.state.selected ? activeButton : null]}>
<TouchableOpacity onPress={() => {
this.setState({ selected: !this.state.selected });
this.props.onPress();
}}>
{
this.btnBackgroundImage()
}
</TouchableOpacity>
</View>
);
}

onChangeText setState only sets one character not the whole string

I accept text input from a search bar and setState to text but its only one character at a time how can I continue to update and add to the state rather than replace what's in state? I feel like this is the intended action but my code does not do this.
class FindRecipesScreen extends Component {
static navigationOptions = {
title: "Find Recipes",
header: null
};
constructor(props) {
super(props);
this.state = {
search: "",
recipe: "",
text: "",
};
}
backToHomePage = () => {
this.props.navigation.navigate("Home");
};
componentDidMount() {
this.props.getRecipeList(this.props.auth.jwt);
}
handleSearch = text => {
console.log("text", text);
this.setState({text: text});
};
render() {
return (
<View style={styles.recipe}>
<View style={styles.recipeBar}>
<ActionNavbar title="Find Recipes"
leftAction={this.backToHomePage}
leftIcon={require("app/assets/icons/cancel.png")}
rightAction={this.backToHomePage}
rightIcon={require("app/assets/icons/filter.png")}/>
</View>
<View>
<View>
<SearchBar
containerStyle={styles.searchContainer}
inputContainerStyle={styles.searchInputContainer}
inputStyle={styles.searchInput}
lightTheme
searchIcon={searchIcon}
round
onChangeText={this.handleSearch}
placeholder="Search Cookbooks"
/>
<View style={styles.forward}>
<Image
style={styles.forwardIcon}
width={18}
height={18}
source={require("app/assets/icons/forward.png")}
/>
</View>
</View>
</View>
</View>
);
}
}
I found the solution... I needed const { search } = this.state; after render but before return with searcher
Use debouncer in the handleSearch function so the state is set after your debounce time.

How to keep the previous state after navigation

//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

How do I disable touchableOpacity?

I am making an appointment app, I have 6 time slots on a given day. The selected slots are stored into a const called "notAvailableSlots" as soon as the component loads. How do I disable the touchableOpacity if "notAvailableSlots" has corresponding values in it, meaning someone has clicked one of the 6 slots already? I know it takes a boolean, but stuck thinking what value to pass...
const availableHours = {
timeSlots: {
slot1: "2:00pm to 2:30pm",
slot2: "2:30pm to 3:00pm",
slot3: "3:00pm to 3:30pm",
slot4: "3:30pm to 4:00pm",
slot5: "4:00pm to 4:30pm",
slot6: "4:30pm to 5:00pm"
}
};
class Appointment extends Component {
constructor(props) {
super(props);
this.state = {
datePicker: false,
date: new Date()
};
}
componentDidMount() {
this.props.fetchDataFromHeroku();
}
render() {
const availability = availableHours.timeSlots;
const notAvailableSlots = this.props.date
.filter(date => {
const month = new Date(date.date).getMonth();
const day = new Date(date.date).getDate();
const year = new Date(date.date).getFullYear();
return (
month === this.state.date.getMonth() &&
day === this.state.date.getDate() &&
year === this.state.date.getFullYear()
);
})
.map(date => date.time_slot);
// console.log(this.state.date);
console.log("not available: ", notAvailableSlots);
return (
<View style={styles.container}>
<Text style={{ backgroundColor: "#00CED1", height: 35 }}>
Hi! Please click on "calendar" to setup an appointment
</Text>
<View>
<Button
style={styles.buttonOne}
title="Make an appointment"
onPress={() => {
const { action, year, month, day } = DatePickerAndroid.open({
date: new Date()
}).then(response => {
this.setState({
datePicker: true,
date: new Date(response.year, response.month, response.day)
});
response.month += 1;
console.log("date", response);
});
}}
/>
{this.state.datePicker
? Object.keys(availability).map((time, i) => {
// console.log(time); this returns slots 1 thru 6
return (
<View key={i} style={styles.slotButton}>
<TouchableOpacity
disabled={true}
onPress={() =>
this.props.addTimeSlotToDatabase(
time,
this.props.user.id,
this.state.date
)
}
>
<Text style={{ alignItems: "center" }}>
{availability[time]}
</Text>
</TouchableOpacity>
</View>
);
})
: null}
</View>
</View>
);
}
}
Simply put the value in the state.
constructor(props) {
super(props);
this.state = {
disabled: false
};
}
render() {
return(
<TouchableOpacity disabled={this.state.disabled}>
<Text>Click</Text>
</TouchableOpacity>
)
}
Sometimes I do like this
import { TouchableOpacity, View } from 'react-native';
const MainView = isDisabled ? View : TouchableOpacity;
return (
<MainView onPress={}>