I have a flatlist with rendered list of items. I need for each item to change circle to checked-circle on click and go back on second click. I tried to do it with changing item prop isChecked but circle doesn't rerender until I go out of the screen and came back. How may I fix my problem?
Here is my rendering code:
const renderItems = ({ item }) => (
<TouchableOpacity
onPress={() => (item.isChecked = !item.isChecked)}
style={
item.isMarked
? {
backgroundColor: '#FE2C55',
flexDirection: 'row',
alignItems: 'center',
height: word_height
}
: { flexDirection: 'row', alignItems: 'center', height: word_height }
}
>
<View
style={{
width: 45,
justifyContent: 'center',
alignItems: 'center',
height: '100%',
backgroundColor: '#F6FFE0'
}}
>
{item.isChecked ? (
<Feather name="check-circle" size={25} color="#3D5201" />
) : (
<Feather name="circle" size={25} color="#3D5201" />
)}
</View>
<View style={styles.word_line}>
<View style={{ width: word_width, paddingLeft: 20 }}>
<Text style={{ fontSize: 20 }}>{item.word}</Text>
</View>
<View style={{ width: word_width, paddingLeft: 20 }}>
<Text style={{ fontSize: 20 }}>{item.translation}</Text>
</View>
</View>
</TouchableOpacity>
);
On this line, you are trying to mutate the props variable, so react will not update the component when the props state is mutated.
onPress={() => (item.isChecked = !item.isChecked)}
To do this, create a separate component (based on the name of the renderItems method, I guess it's just a function in the component) and add state to it.
Use useState and the initial state value that was taken from the props initialIsChecked
const Item = ({isMarked, isChecked: initialIsChecked, word, translation}) => {
const [isChecked, setIsChecked] = useState(initialIsChecked);
const handleClick = () => {
setIsChecked((prev) => !prev);
};
return (
<TouchableOpacity
onPress={handleClick}
style={
isMarked
? {
backgroundColor: '#FE2C55',
flexDirection: 'row',
alignItems: 'center',
height: word_height,
}
: {flexDirection: 'row', alignItems: 'center', height: word_height}
}>
<View
style={{
width: 45,
justifyContent: 'center',
alignItems: 'center',
height: '100%',
backgroundColor: '#F6FFE0',
}}>
{isChecked ? (
<Feather name="check-circle" size={25} color="#3D5201" />
) : (
<Feather name="circle" size={25} color="#3D5201" />
)}
</View>
<View style={styles.word_line}>
<View style={{width: word_width, paddingLeft: 20}}>
<Text style={{fontSize: 20}}>{word}</Text>
</View>
<View style={{width: word_width, paddingLeft: 20}}>
<Text style={{fontSize: 20}}>{translation}</Text>
</View>
</View>
</TouchableOpacity>
);
};
Then the list component should look something like this:
const List = () => {
return <ScrollView>
items.map((item) => (
<Item
key={item.id} // if there is id
isMarked={item.isMarked}
isChecked={item.isChecked}
word={item.word}
translation={item.translation}
/>
)
</ScrollView>;
};
Related
From App.js, I declare the "FollowingScreen", which is made of a module that exports "Following"
export const FollowingScreen = ({route, navigation}) => {
return (
<ScrollView style={styles.scrollView}>
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: "#262423" }}>
<Following />
</View>
</ScrollView>
);
}
"Following" is exported by a file called "following.js". From "following.js" I want to navigate to ProfileScreen:
import { useNavigation } from '#react-navigation/native';
class Following extends Component {
...
...
renderItem = ({item}, navigation) => (
<ListItem bottomDivider>
<ListItem.Content style={{width: '100%', display: 'flex', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center'}}>
<ListItem.Title>{item.title}</ListItem.Title>
<TouchableOpacity
onPress={() => navigation.navigate("ProfileScreen", {userInfo: {uri: item.probability, username: item.country_id, id_user: item.id_user}})}
style={{ flexDirection: 'row'}}
>
<Image
style={{ borderRadius: 50 }}
source={{ uri: item.probability, width: 48, height: 48 }}
/>
</TouchableOpacity>
<TouchableOpacity
onPress={() => navigation.navigate("ProfileScreen", {userInfo: {uri: item.probability, username: item.country_id, id_user: item.id_user}})}
style={{ flexDirection: 'row'}}
>
<ListItem.Subtitle style={{color: '#000'}}>
<Text style={{fontFamily: 'Montserrat_600SemiBold' }}>{item.name} {item.surname}</Text>
{"\n"}
<Text style={{fontFamily: 'Montserrat_600SemiBold' }}>#{item.country_id}</Text>
{"\n"}
{"\n"}
<Text style={{fontFamily: 'Montserrat_600SemiBold' }}>{item.followers}</Text>
{"\n"}
<Text style={{fontFamily: 'Montserrat_600SemiBold' }}>{item.total}</Text> Total
</ListItem.Subtitle>
</TouchableOpacity>
<Button
buttonStyle={{backgroundColor: "#a6aba7", padding: 9, textAlign: "right", borderRadius: 10, display: item.isFollowing=="Same user" ? "none" : "flex"}}
title={item.isFollowing}
onPress={() => {
if(item.isFollowing=="Follow"){
this.follow(item.id_user);
}
else if(item.isFollowing=="Unfollow"){
this.unfollow(item.id_user);
}
else if(item.isFollowing=="Same user"){
//alert("Same user");
}
}}
/>
</ListItem.Content>
</ListItem>
);
}
unfortunately, I get "undefined is not an object (evaluating 'navigation.navigate')"
You are not passing navigation as a prop to the Following component so change your FollowingScreen component likewise :
export const FollowingScreen = ({route, navigation}) => {
{/** Rest Of Code **/}
<Following navigation={navigation}/>
{/** Rest of Code **/}
}
Then in Following class use this.props.navigation.navigate(....).
You need to declare "navigation" before calling it:
const navigation = useNavigation();
right before
renderItem = (...)
Hello I make an app in React Native !
I try to make three active or not active button. So i define a state with
const [activeLabel, setActiveLabel] = useState(0);
And on my Text compenent I have
activeLabel === 1 ? styles.selectedLabel : styles.notSelectedLabel
onPress={() => setActiveLabel(1)}
When I initialize I set activeLabel at 0 and when I click and other component with console.log activeLabel stay at 0.
I make something wrong ?
Thanks you !
Here my component Labels
function Labels({
setDataNumber,
title,
color,
firstLabel,
secondLabel,
thirdLabel,
}) {
const [activeLabel, setActiveLabel] = useState(0);
return (
<View style={{ flexDirection: "row" }}>
<Text style={{ color: color, fontSize: 20, margin: 10 }}>{title}</Text>
<View
style={{ flexDirection: "row", justifyContent: "flex-end", flex: 1 }}
>
<Text
style={{
color: color,
borderColor: color,
...(activeLabel === 0
? styles.selectedLabel
: styles.notSelectedLabel),
}}
onPress={() => setActiveLabel(0), () => setDataNumber(0)}
>
{firstLabel}
</Text>
<Text
style={{
color: color,
borderColor: color,
...(activeLabel === 1
? styles.selectedLabel
: styles.notSelectedLabel),
}}
onPress={() => setActiveLabel(1), () => setDataNumber(1)}
>
{secondLabel}
</Text>
<Text
style={{
color: color,
borderColor: color,
...(activeLabel === 2
? styles.selectedLabel
: styles.notSelectedLabel),
}}
onPress={() => setActiveLabel(2), () => setDataNumber(2)}
>
{thirdLabel}
</Text>
</View>
</View>
);
}
#sidharth-rathi offered me a solution!
function Labels({ setActiveLabel, title, color, activeIndex, labels = [] }) {
return (
<View style={{ flexDirection: "row" }}>
<Text style={{ color: color, fontSize: 20, margin: 10 }}>{title}</Text>
<View
style={{ flexDirection: "row", justifyContent: "flex-end", flex: 1 }}
>
{labels.map((el, index) => (
<Text
style={{
color: color,
borderColor: color,
...(activeIndex === index
? styles.selectedLabel
: styles.notSelectedLabel),
}}
onPress={() => setActiveLabel(index)}
>
{el}
</Text>
))}
</View>
</View>
);
}
I am trying to implement a function in Expo to filter my data using checkboxes. I have already completed my checkboxes and designed them accordingly. The data to be filtered is pulled from the Firebase database and displayed in the form of a list on my page. I have also created a button for the filtering, which is used so that when a user clicks this button, the filtering takes place according to the selection of the respective boxes. Attached is a picture that shows what has already been implemented and below the code for it. I would be very grateful if someone could help me with this, as I am relatively new to React Native and have not found anything in this regard.
Thanks in advance
Anbieterliste-Screen
function MyCheckbox() {
const [checked, onChange] = useState(false);
function onCheckmarkPress() {
onChange(!checked);
}
return (
<Pressable
style={[styles.checkboxBase, checked && styles.checkboxChecked]}
onPress={onCheckmarkPress}>
{checked && <Ionicons name="checkmark" size={18} color="white" />}
</Pressable>
);
}
export default function Anbieter({ route, navigation }) {
//CONSTS WHICH WE GOT FROM THE HOMEPAGE AND DECLARATION
const { latitude, longitude, address } = route.params;
var getLat = latitude;
var getLong = longitude;
var getAddress = JSON.stringify(address);
const [restaurentList, setRestaurentList] = useState()
const [currentUsers, setCurrentUsers] = useState()
const [ranges, setRanges] = useState(1)
const [showRange, setShowRange] = useState(false)
// THIS IS A LIST WHICH DISPLAY ALL RESTAURANTS BY GETTING DATA IN PARAMS IN NAME OF DATA
const ListButton = ({ title, data }) => {
return (
<TouchableOpacity onPress={() => { navigation.navigate('Produktubersicht', { data }) }} style={[styles.itemContainer]}>
<Image source={{ uri: data.anbieterImg }} style={{ width: '90%', marginLeft: '5%', height: 160 }} />
<Text style={{ fontSize: 16, fontWeight: "bold", marginLeft: 20 }}>{data.firmenname}</Text>
<Text style={{ fontSize: 16, fontWeight: "bold", marginLeft: 20, width: '90%' }}>Adresse:
<Text style={{ fontSize: 16, fontWeight: 'normal' }}>{data.adresse}</Text>
</Text>
<Text style={{ fontSize: 16, fontWeight: "bold", marginLeft: 20, width: '90%' }}>Kategorie:
<Text style={{ fontSize: 16, fontWeight: 'normal' }}>{data.kategorie}</Text>
</Text>
</TouchableOpacity>
);
}
// THIS FUNCTION IS USE TO CALL ALL RESTAURANT FROM FIREBASE DATABASE
const getRestaurents = async () => {
let arr = []
// THIS IS FIREBASE API ALL DATA IS COMING FROM FIREBASE
var ar = await firebase.database().ref("/anbieter/").once("child_added", snapshot => {
var obj = snapshot.val();
obj.id = snapshot.key;
arr.push(obj);
});
// ALL DATA OF RESTAURANT IS STORING IN STATE HERE THEN FROM HERE ALL DATA WILL DISPLAY
setRestaurentList(arr)
}
var users = firebase.auth().currentUser;
useEffect(() => {
// WE CALL GET RESTAURANTS API HERE BECAUSE THIS USEEFFECT JUST CALL ONCE WHEN COMPONENT RENDER
console.log(users, 'users');
getRestaurents()
}, []);
// THIS IS SIGN OUT BUTTON , WHEN USER CLICK FOR SIGNOUT THEN IT ASKS WHETHER HE/SHE IS SURE TO DO SO
const signOutFunc = async () => {
Alert.alert(
"Ausloggen?",
"Sind Sie sicher, dass Sie sich ausloggen möchten?",
[
{
text: "Bestätigen", onPress: async () => {
await AsyncStorage.removeItem('userName')
await AsyncStorage.removeItem('order')
firebase.auth().signOut();
navigation.navigate('Homepage');
}
},
{
text: "Abbrechen",
style: "cancel"
}
]
);
}
return (
<ScrollView>
{/* THIS IS THE PART OF ICON WHERE LOGIN , SIGNOUT , Bestellverlauf AND Warenkorb ICON ARE HERE */}
<View style={styles.container}>
<View style={{ flexDirection: 'row', justifyContent: 'space-between', marginRight: 5, marginVertical: 10 }}>
{users ?
<TouchableOpacity onPress={() => { signOutFunc() }}>
<Entypo name="log-out" size={30} color="black" />
</TouchableOpacity>
: null}
{users ?
<View style={{ flexDirection: 'row', }}>
<TouchableOpacity onPress={() => { navigation.navigate('Bestellverlauf') }} style={{ marginRight: 20 }}>
<Fontisto name="prescription" size={30} color="black" />
</TouchableOpacity>
<TouchableOpacity onPress={() => { navigation.navigate('Warenkorb') }}>
<Feather name="shopping-bag" size={30} color="black" />
</TouchableOpacity>
</View>
:
<TouchableOpacity style={{ flexDirection: 'row' }} onPress={() => { navigation.navigate('Anmelden') }}>
<FontAwesome5 name="user" size={30} color="black" />
<Text style={{ margin: 10 }}>Registration/Login</Text>
</TouchableOpacity>
}
</View>
<Text style={styles.textFirst}>Ermittelte Adresse:</Text>
<View style={{ alignContent: 'center', flexDirection: 'row', width: '90%' }}>
<Text style={{ marginBottom: 15, marginTop: 10, marginHorizontal: 10 }}>{getAddress} </Text>
<TouchableOpacity onPress={() => { setShowRange(!showRange) }}>
<MaterialCommunityIcons name="filter-plus" size={30} color="grey" />
</TouchableOpacity>
</View>
{/* THIS IS RANGE SLIDER FOR SORTING ALL RESTAURANTS */}
{showRange ?
<View>
<View style={{ flexDirection: 'row', justifyContent: "space-between" }}>
<Text style={{ marginLeft: '3%', fontSize: 14, fontWeight: 'bold' }}> Entfernung festlegen!</Text>
<Text style={{ marginLeft: '3%' }}> {Math.round(ranges)} km</Text>
</View>
<Slider maximumValue={100} style={{ width: '90%', marginLeft: '5%', marginTop: 10, }} value={ranges} onValueChange={(e) => setRanges(e)} />
<View style={{ marginTop: 10 }}>
<Text style={{ marginLeft: '3%', fontSize: 14, fontWeight: 'bold', marginBottom: 10, }}>Filterung nach Kategorie</Text>
<View style={styles.checkboxContainer}>
<MyCheckbox />
<Text style={styles.checkboxLabel}>Backware</Text>
</View>
<View style={styles.checkboxContainer}>
<MyCheckbox />
<Text style={styles.checkboxLabel}>Bioprodukte</Text>
</View>
<View style={styles.checkboxContainer}>
<MyCheckbox />
<Text style={styles.checkboxLabel}>Feinkost</Text>
</View>
<View style={styles.checkboxContainer}>
<MyCheckbox />
<Text style={styles.checkboxLabel}>Griechische Spezialitäten</Text>
</View>
<View style={styles.checkboxContainer}>
<MyCheckbox />
<Text style={styles.checkboxLabel}>Molkerei</Text>
</View>
<View style={styles.checkboxContainer}>
<MyCheckbox />
<Text style={styles.checkboxLabel}>Türkische Spezialitäten</Text>
</View>
<Button title="Filter anwenden..." color='#5271FF'/>
</View>
</View>
: null
}
<Text style={styles.textSecond}>Sie können gerne die Filterfunktion verwenden, indem Sie oben auf den Symbol klicken...</Text>
{restaurentList && restaurentList.map((val, i) => {
return <ListButton key={i} title={val.firmenname} data={val} />
})}
</View>
</ScrollView>
);
}
A better approach to avoid duplication of code is to create a filterList array and create dynamic filters component.
I modified your code, check the comments for the explanation.
function MyCheckbox({addFilter, removeFilter, filterIndex}) { // ADD THIS PROPS TO ADD AND REMOVE FILTERS
const [checked, onChange] = useState(false);
function onCheckmarkPress() {
onChange(!checked);
checked ? addFilter(filterIndex) : removeFilter(filterIndex)
}
return (
<Pressable
style={[styles.checkboxBase, checked && styles.checkboxChecked]}
onPress={onCheckmarkPress}>
{checked && <Ionicons name="checkmark" size={18} color="white" />}
</Pressable>
);
}
export default function Anbieter({ route, navigation }) {
//CONSTS WHICH WE GOT FROM THE HOMEPAGE AND DECLARATION
const { latitude, longitude, address } = route.params;
var getLat = latitude;
var getLong = longitude;
var getAddress = JSON.stringify(address);
const [restaurentList, setRestaurentList] = useState()
const [filteredRestaurantList, setFilteredRestaurentList] = useState() // <-- ADD THIS STATE TO KEEP TRACK OF THE FILTERED LIST TO DISPLAY
const [currentUsers, setCurrentUsers] = useState()
const [ranges, setRanges] = useState(1)
const [showRange, setShowRange] = useState(false)
const [filters, setFilters] = useState([]) // <-- ADD THIS STATE TO KEEP TRACK OF THE FILTERS SELECTED
const filterList = ["Backware", "Bioprodukte", "Feinkost", "Griechische Spezialitäten"] // <--- CREATE A FILTER ARRAY
const addFilter = (filterIndex) => { // <-- FUNCTION ADD FILTER
setFilters([...filters, filterList[filterIndex]])
}
const removeFilter = (filterIndex) => { // <-- FUNCTION REMOVE FILTER
const index = filters.indexOf(filterList[filterIndex]);
const newFilters = [...filters];
newFilters.splice(index, 1)
setFilters(newFilters)
}
// THIS IS A LIST WHICH DISPLAY ALL RESTAURANTS BY GETTING DATA IN PARAMS IN NAME OF DATA
const ListButton = ({ title, data }) => {
return (
<TouchableOpacity onPress={() => { navigation.navigate('Produktubersicht', { data }) }} style={[styles.itemContainer]}>
<Image source={{ uri: data.anbieterImg }} style={{ width: '90%', marginLeft: '5%', height: 160 }} />
<Text style={{ fontSize: 16, fontWeight: "bold", marginLeft: 20 }}>{data.firmenname}</Text>
<Text style={{ fontSize: 16, fontWeight: "bold", marginLeft: 20, width: '90%' }}>Adresse:
<Text style={{ fontSize: 16, fontWeight: 'normal' }}>{data.adresse}</Text>
</Text>
<Text style={{ fontSize: 16, fontWeight: "bold", marginLeft: 20, width: '90%' }}>Kategorie:
<Text style={{ fontSize: 16, fontWeight: 'normal' }}>{data.kategorie}</Text>
</Text>
</TouchableOpacity>
);
}
// THIS FUNCTION IS USE TO CALL ALL RESTAURANT FROM FIREBASE DATABASE
const getRestaurents = async () => {
let arr = []
// THIS IS FIREBASE API ALL DATA IS COMING FROM FIREBASE
var ar = await firebase.database().ref("/anbieter/").once("child_added", snapshot => {
var obj = snapshot.val();
obj.id = snapshot.key;
arr.push(obj);
});
// ALL DATA OF RESTAURANT IS STORING IN STATE HERE THEN FROM HERE ALL DATA WILL DISPLAY
setRestaurentList(arr)
setFilteredRestaurentList(arr)
}
var users = firebase.auth().currentUser;
useEffect(() => {
// WE CALL GET RESTAURANTS API HERE BECAUSE THIS USEEFFECT JUST CALL ONCE WHEN COMPONENT RENDER
console.log(users, 'users');
getRestaurents()
}, []);
useEffect(() => { // <--- ADD THIS TO UPDATE THE FILTER RESTAURANT LIST EVERY TIME THAT THE FILTER ARRAY CHANGE
const rList = [...restaurentList];
if (filters.length) {
const filteredList = rList.filter(r => {
const toAdd = filters.indexOf(r.category)
if (toAdd !== -1) {
return r
}
})
setFilteredRestaurentList(filteredList)
}else { // <-- IF THERE ARE NO FILTER; RESET TO ORIGINAL LIST
setFilteredRestaurentList(rList)
}
}, [filters]);
return (
<ScrollView>
{/* THIS IS THE PART OF ICON WHERE LOGIN , SIGNOUT , Bestellverlauf AND Warenkorb ICON ARE HERE */}
<View style={styles.container}>
<View style={{ flexDirection: 'row', justifyContent: 'space-between', marginRight: 5, marginVertical: 10 }}>
{users ?
<TouchableOpacity onPress={() => { signOutFunc() }}>
<Entypo name="log-out" size={30} color="black" />
</TouchableOpacity>
: null}
{users ?
<View style={{ flexDirection: 'row', }}>
<TouchableOpacity onPress={() => { navigation.navigate('Bestellverlauf') }} style={{ marginRight: 20 }}>
<Fontisto name="prescription" size={30} color="black" />
</TouchableOpacity>
<TouchableOpacity onPress={() => { navigation.navigate('Warenkorb') }}>
<Feather name="shopping-bag" size={30} color="black" />
</TouchableOpacity>
</View>
:
<TouchableOpacity style={{ flexDirection: 'row' }} onPress={() => { navigation.navigate('Anmelden') }}>
<FontAwesome5 name="user" size={30} color="black" />
<Text style={{ margin: 10 }}>Registration/Login</Text>
</TouchableOpacity>
}
</View>
<Text style={styles.textFirst}>Ermittelte Adresse:</Text>
<View style={{ alignContent: 'center', flexDirection: 'row', width: '90%' }}>
<Text style={{ marginBottom: 15, marginTop: 10, marginHorizontal: 10 }}>{getAddress} </Text>
<TouchableOpacity onPress={() => { setShowRange(!showRange) }}>
<MaterialCommunityIcons name="filter-plus" size={30} color="grey" />
</TouchableOpacity>
</View>
{/* THIS IS RANGE SLIDER FOR SORTING ALL RESTAURANTS */}
{showRange ?
<View>
<View style={{ flexDirection: 'row', justifyContent: "space-between" }}>
<Text style={{ marginLeft: '3%', fontSize: 14, fontWeight: 'bold' }}> Entfernung festlegen!</Text>
<Text style={{ marginLeft: '3%' }}> {Math.round(ranges)} km</Text>
</View>
<Slider maximumValue={100} style={{ width: '90%', marginLeft: '5%', marginTop: 10, }} value={ranges} onValueChange={(e) => setRanges(e)} />
<View style={{ marginTop: 10 }}>
<Text style={{ marginLeft: '3%', fontSize: 14, fontWeight: 'bold', marginBottom: 10, }}>Filterung nach Kategorie</Text>
{filterList.map((filterItem, index) => (
<View
key={index}
style={styles.checkboxContainer}>
<MyCheckbox
addFilter={addFilter} // <-- ADD THIS PROP
removeFilter={removeFilter} // <-- ADD THIS PROP
filterIndex={index} // <-- ADD THIS PROP
/>
<Text style={styles.checkboxLabel}>filterItem</Text>
</View>
))}
<Button title="Filter anwenden..." color='#5271FF'/>
</View>
</View>
: null
}
<Text style={styles.textSecond}>Sie können gerne die Filterfunktion verwenden, indem Sie oben auf den Symbol klicken...</Text>
{filteredRestaurantList && filteredRestaurantList.map((val, i) => {
return <ListButton key={i} title={val.firmenname} data={val} />
})}
</View>
</ScrollView>
);
}
Below object response I am getting , on FAILURE response I am trying to call function that open modal .
But I guess its wrong approach, please correct me . If I call same function button click then Modal is coming . Please how can I open modal on failure and success I'll got o next page screen .
Please suggest me.
/// Below response //////////
Object response
validateUserResponse:
reference_id: "NxNxNxNxNxNxNxNxNxNxNxN"
status: "FAILURE"
/////////////////////////
this.state={
isModalVisible: false,
}
_toggleModal = () =>
this.setState({ isModalVisible: !this.state.isModalVisible });
render(){
const {validateUserResponse} = this.props;
if (!_.isEmpty(validateUserResponse)) {
validateUserResponse.status==='FAILURE'? this._toggleModal():LoadScreen.bind(that, 2, validateUserResponse)();
}
return (
<View>
<Modal
isVisible={this.state.isModalVisible}
onBackButtonPress={() => this._toggleModal()}
onBackdropPress={() => this._toggleModal()}
style={{ margin: 0 }}
>
<View style={style.modalContainer}>
<View style={style.innerContainer}>
<View style={style.detailsContainer}>
<View style={{ flexDirection: 'column', alignItems: 'flex-end', marginTop: -40 }}>
<TouchableOpacity onPress={() => this._toggleModal()} >
<Image source={CLOSE_W} />
</TouchableOpacity>
</View>
<View style={{ flexDirection: 'column', justifyContent: 'center' }}>
<View style={{ flexDirection: 'row', justifyContent: 'center', marginTop: 10, alignContent: 'center', alignItems: 'center', alignSelf: 'center' }}>
<IconSmall icon="report-problem" type="MaterialIcons" style={{ color: 'red', paddingRight: 5, paddingBottom: 3 }} />
<Text>CUSTOMER E-VALIDATION FAILED</Text>
</View>
<View style={{
justifyContent: 'center',
height: 2,
margin: 5,
borderBottomWidth: 1,
borderBottomColor: 'grey',
paddingBottom: 10
}} />
</View>
<View style={{ flexDirection: 'column', marginBottom: 10 }}>
<RegularText text={'Status'} textColor='grey' style={{ marginBottom: 5 }} />
<SmallText text={validateUserResponse.status} textColor='red' />
</View>
<View style={{ padding: 10 }}>
<PrimaryBtn label={'Validate Again'} disabled={false}
onPress={() => this._toggleModal()} />
</View>
<View style={{ padding: 10 }}>
<YellowBtn label={'Go to Dashboard'} disabled={false}
onPress={() => this._gotoDashboard()} />
</View>
</View>
</View>
</View>
</Modal>
</View>
)
Thanks
You should not change the state in render method . "_toggleModal" is method which change state and it is bad approach.
You should use getderivedstatefromprops
getDerivedStateFromProps is invoked right before calling the render
method, both on the initial mount and on subsequent updates. It should
return an object to update the state, or null to update nothing.
static getDerivedStateFromProps(nextProps, prevState){
if(!_.isEmpty(nextProps.validateUserResponse) && nextProps.validateUserResponse.status==='FAILURE'){
return { isModalVisible: true};
}
else return null;
}
I want to send the data of a text input that is stored in a variable to another screen and show the data that was saved in said variable
Try to pass the state of the variable by react-navigation but the problem is that I have 3 screens and I want to pass the data stored in the variable text from screen 1 to screen 3
class Screen1 extends Component {
constructor(props) {
super(props);
this.state = {
text: '',
percentage: ''
};
}
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state
var data = {
textData: params.text
}
return {
headerLeft: (
<View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
<AntDesign
name="left"
color="rgba(0,0,0,0.5)"
size={30}
style={{ marginLeft: 5 }}
/>
<Text style={{ marginLeft: 20, color: '#000', fontSize: 17, fontWeight: 'bold' }}>Crear regalo</Text>
</View>
),
headerRight: (
<View>
<TouchableOpacity
disabled={navigation.getParam('isDisable')} // get value from params and pass it to disabled props
onPress={() => navigation.navigate('2', { data })}
style={styles.Btn}>
<Text style={styles.TxtBtn}>Siguiente</Text>
</TouchableOpacity>
</View>
),
}
};
// set by a default value in componentDidMount to make the next button disable initially
componentDidMount() {
Alert.alert('Advertencia', 'Ingrese el porcentaje de su descuento');
this.props.navigation.setParams({ isDisable: true });
}
render() {
return (
<View style={styles.container}>
<View style={styles.Box}>
<ImageBackground source={require('../Icons/Regalo.png')} style={styles.Image}>
<View style={styles.ContainerInput}>
<TextInput
style={{ textAlign: 'center', color: '#fff', fontSize: 40, }}
type="numeric"
placeholder="%"
value={this.state.text} //set value from state
onChangeText={(text) => {
//when text length is greater than 0 than next button active otherwise it will be disable
let isDisable = text.length > 0 ? false : true
//set value in the state
this.setState({ text: text })
// set value to params
this.props.navigation.setParams({ isDisable: isDisable });
}} />
<Text style={{ fontSize: 40, color: '#fff', textAlign: 'center' }}>
{this.state.text.split(' ').map((word) => word && '%').join(' ')}
</Text>
</View>
</ImageBackground>
</View>
</View>
);
}
}
export default Screen1;
My Screen Two:
class Screen2 extends Component {
constructor(props) {
super(props);
this.state = {
textData: this.props.navigation.state.params.data.textData,
text: ''
};
}
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state
var data = {
textData: params.textData
}
return {
headerLeft: (
<View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
<AntDesign
name="left"
color="rgba(0,0,0,0.5)"
size={30}
style={{ marginLeft: 5 }}
onPress={() => navigation.navigate('1')}
/>
<Text style={{ marginLeft: 20, color: '#000', fontSize: 17, fontWeight: 'bold' }}>Crear regalo</Text>
</View>
),
headerRight: (
<View>
<TouchableOpacity
disabled={navigation.getParam('isDisable')} // get value from params and pass it to disabled props
onPress={() => navigation.navigate('3', { data })}
style={styles.Btn}>
<Text style={styles.TxtBtn}>Crear</Text>
</TouchableOpacity>
</View>
),
}
};
componentDidMount() {
this.props.navigation.setParams({ isDisable: true });
}
render() {
return (
<View style={styles.container}>
<View style={styles.InputContainer}>
<TextInput
multiline
style={styles.Input}
type="numeric"
placeholder="Describa los términos y condificones de tu regalos"
placeholderTextColor="rgb(196,196,196)"
value={this.state.text} //set value from state
onChangeText={(text) => {
//when text length is greater than 0 than next button active otherwise it will be disable
let isDisable = text.length > 1 ? false : true
//set value in the state
this.setState({ text: text })
// set value to params
this.props.navigation.setParams({ isDisable: isDisable });
}} />
</View>
</View>
);
}
}
export default Screen2;
My Screen Three:
class Screen3 extends Component {
constructor(props) {
super(props);
this.state = {
textData: this.props.navigation.state.params.data.textData,
text: '',
percentage: '',
};
}
static navigationOptions = ({ navigation }) => ({
headerLeft: (
<View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
<AntDesign
name="left"
color="rgba(0,0,0,0.5)"
size={30}
style={{ marginLeft: 5 }}
onPress={() => navigation.navigate('2')}
/>
<Text style={{ marginLeft: 20, color: '#000', fontSize: 17, fontWeight: 'bold' }}>Crear regalo</Text>
</View>
),
headerRight: (
<View>
<TouchableOpacity
disabled={navigation.getParam('isDisable')} // get value from params and pass it to disabled props
onPress={() => navigation.navigate('4')}
style={styles.Btn}>
<Text style={styles.TxtBtn}>Crear</Text>
</TouchableOpacity>
</View>
),
});
// set by a default value in componentDidMount to make the next button disable initially
componentDidMount() {
this.props.navigation.setParams({ isDisable: true });
}
render() {
let datos = [{
value: 'Banana',
}, {
value: 'Mango',
}, {
value: 'Pear',
}];
var data = {
textData: this.state.textData
}
return (
<View style={styles.container}>
<View style={styles.BoxandInput}>
<View style={styles.ContainerInput}>
<TextInput
style={styles.Input}
multiline
placeholder='Escriba una Descripcion'
placeholderTextColor="rgb(196,196,196)"
maxLength={203}
/>
</View>
<View style={styles.Box}>
<ImageBackground
source={require('../Icons/Regalo.png')}
style={styles.Image}>
<View style={styles.ContainerText}>
<Text style={styles.TextBox}>{data}</Text>
</View>
</ImageBackground>
</View>
</View>
<View style={styles.Regalos}>
<View style={{ justifyContent: 'center', alignItems: 'center', flexDirection: 'row' }}>
<Text style={styles.line}>--------------------------</Text>
<Text style={styles.RegalosText}>Cantidad de Regalos</Text>
<Text style={styles.line}>--------------------------</Text>
</View>
<View style={{ justifyContent: 'center', alignItems: 'center', marginTop: 30 }}>
<TextInput
style={styles.RegalosInput}
placeholder='0'
placeholderTextColor='#000'
maxLength={6}
type='numeric'
/>
<View style={styles.LineInput} />
<Text style={{ fontSize: 10, color: '#ccc', textAlign: 'center', marginTop: 5 }}>60 regalos Disponibles</Text>
<TouchableOpacity style={{ marginTop: 15 }}>
<Text style={{ fontSize: 10, color: 'cyan', textAlign: 'center' }}>Comprar Regalos</Text>
</TouchableOpacity>
</View>
</View>
<View style={styles.ContainerServices}>
<View style={{ justifyContent: 'center', alignItems: 'center', flexDirection: 'row' }}>
<Text style={styles.line}>-----------------------------------</Text>
<Text style={styles.RegalosText}>Servicios</Text>
<Text style={styles.line}>-----------------------------------</Text>
</View>
<Dropdown
dropdownMargins={{ min: 5, max: 10 }}
label='Favorite Fruit'
data={datos}
/>
</View>
</View>
);
}
}
export default
This Problem
You can create a data object and you can send it with navigation to next UI. You can pass the data object from UI 1 to UI 2 and then you can send it UI 3 from UI 2.
In the first UI you can create data variable like,
var data = {
textData: text
}
Include the above code inside navigationOptions of your code.
Then in the navigation call include the data object as well.
onPress={() => navigation.navigate('2', {data})}
In the second UI assign the passed value to a variable inside the constructor.
constructor(props) {
super(props);
this.state = {
textData: this.props.navigation.state.params.data. textData,
}
}
Then when you are going to navigate to the third UI create a data variable and send it as previously done.
var data = {
textData: this.state.textData
}
Pass this variable with navigate.navigation and access it from third UI similar as in the second UI.