I have rendered data from an array / JSON and its shows on screen. When I click on an option its heiglights the box on which I have clicked. But I want to heightlight multiple options or want to choose multiple options from array.
I am not getting how to do that. It only shows only one option and when I click click on another otion it heighlights the option but dehighlights the previous option.
Please suggest me solution for that. I have share image and code below -
Image:
enter image description here
Code:
import React, {useContext} from 'react';
import {
Dimensions,
Image,
StatusBar,
Text,
TouchableHighlight,
} from 'react-native';
import {Box, Button, ScrollView} from 'native-base';
import {useState} from 'react';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import {styles} from './createHabitStyles';
import {ApplicationContext} from '../../../context/application_ctx';
import {IconCheck, IconCircleBack} from '../../../svgIcons/icons';
export function ChooseTechnique({navigation, choose}) {
const [chooseButton, setChooseButton] = useState();
const {habitNavigation,setHabitNavigation,chooseSpan} =
useContext(ApplicationContext);
const {techniques, setTechniques} = useContext(ApplicationContext);
let techniqueChooser = [
{button: 'Mood Journal',src:require('../../../assets/images/techniqueBackgrounds/journal.jpg')},
{button: 'Meditation',src:require('../../../assets/images/techniqueBackgrounds/meditation.jpg')},
{button: 'ABCD',src:require('../../../assets/images/techniqueBackgrounds/abcd.jpg')},
{button: 'Optimism',src:require('../../../assets/images/techniqueBackgrounds/optimism1.jpg')},
{button: 'Journal',src:require('../../../assets/images/techniqueBackgrounds/journal.jpg')},
{button: 'Motivation',src:require('../../../assets/images/techniqueBackgrounds/motivation.jpg')},
{button: 'Defusion',src:require('../../../assets/images/techniqueBackgrounds/defusion.jpg')},
{button: 'Values',src:require('../../../assets/images/techniqueBackgrounds/goals.jpg')},
{button: 'Goals',src:require('../../../assets/images/techniqueBackgrounds/values.jpg')},
{button: 'Thought Record',src:require('../../../assets/images/techniqueBackgrounds/thought.jpg')},
{button: 'Breathe',src:require('../../../assets/images/techniqueBackgrounds/breathe.jpg')},
];
return (
<>
<StatusBar
backgroundColor={'#F5F5F5'}
translucent={false}
barStyle={'dark-content'}
/>
<Box style={styles.MainBox}>
<ScrollView>
<Box style={{height: '6%', alignItems: 'center'}}>
<Text style={styles.stepperTxt}>Create Habit</Text>
</Box>
<IconCircleBack
onPress={() => setHabitNavigation(0)}
style={{...styles.iconBack, top: '2.2%'}}
/>
<Box style={styles.choosenBox}>
<Box
style={styles.choosenButton}>
<Text style={{fontSize: 15, color: '#5D535C'}}>
{chooseSpan.but}
</Text>
</Box>
{chooseButton !== undefined ? (
<Box
style={styles.choosenButtonDynamic}>
<Text style={{fontSize: 15, color: '#5D535C'}}>
{techniques}
</Text>
</Box>
) : (
''
)}
</Box>
<Box style={{height: '6%', marginTop: '2%'}}>
<Text style={styles.headTxt}>Choose a technique</Text>
<Text
style={styles.subHeading}>
Create a habit from any one of your susbcribed techniques
</Text>
</Box>
<Box style={{height: 1050}}>
<Box style={{alignItems: 'center'}}>
{techniqueChooser.map((data, i) => {
return (
<TouchableHighlight
key={i}
underlayColor={'none'}
onPress={() => {
setChooseButton(i), setTechniques(data.button);
}}
style={styles.cardTechniques}>
<>
{chooseButton === i ? <IconCheck style={{position:'absolute',right:10,bottom:"10%",zIndex:1}} /> : ""}
<Image
style={styles.imageOptimism}
resizeMethod="scale"
resizeMode="cover"
source={data.src}
/>
<Image
style={{
...styles.imageBackdrop,
display: `${chooseButton === i ? 'none' : 'flex'}`,
}}
resizeMethod="scale"
resizeMode="cover"
source={require('../../../assets/images/techniqueBackgrounds/backdrop.png')}
/>
<Box
style={styles.buttonTechnique}>
<Text
style={{
fontSize: 14,
fontWeight: 'bold',
color: '#5D535C',
}}>
{data.button}
</Text>
</Box>
</>
</TouchableHighlight>
);
})}
</Box>
</Box>
</ScrollView>
<Box
style={{
position: 'absolute',
bottom: '3%',
width: '100%',
alignItems: 'center',
}}>
<Button
isDisabled={chooseButton !== undefined ? false : true}
style={{
...styles.button2,
backgroundColor: `${
chooseButton !== undefined ? '#36A2D0' : '#6D7A82'
}`,
}}
isLoadingText="Continue"
spinnerPlacement="end"
onPress={() =>{techniques === "Meditation" ? setHabitNavigation(4) : techniques === 'Breathe' ? setHabitNavigation(6) : setHabitNavigation(3)}}>
<MaterialIcons
name="arrow-forward-ios"
style={{
fontSize: 20,
color: `${chooseButton !== undefined ? 'white' : 'black'}`,
}}
/>
</Button>
</Box>
</Box>
</>
);
}
Instead of setting individual id to your state, you add your id to an array then set that array to your state.
onPress={() => {
let newArray = [...chooseButton, i];
setChooseButton(newArray),
setTechniques(data.button);
}}
You then use that array to conditionally render your IconCheck by checking if the id exists in the chooseButton array.
Related
I want to select the elements rendered using json array data,
i am rendering the elements using json array where only most recent clicked element is getting select,i want to select every clicked element,like state of previously clicked element should be saved.
In simple words when the element is clicked first time then it will be selected and when i click next element then the previous clicked element should remain selected.Click here to check image
import React, {useContext} from 'react';
import {
Dimensions,
Image,
StatusBar,
Text,
TouchableHighlight,
} from 'react-native';
import {Box, Button, ScrollView} from 'native-base';
import {useState} from 'react';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import {styles} from './createHabitStyles';
import {ApplicationContext} from '../../../context/application_ctx';
import {IconCheck, IconCircleBack} from '../../../svgIcons/icons';
export function ChooseTechnique({navigation, choose}) {
const [chooseButton, setChooseButton] = useState();
const {habitNavigation,setHabitNavigation,chooseSpan} =
useContext(ApplicationContext);
const {techniques, setTechniques} = useContext(ApplicationContext);
let techniqueChooser = [
{button: 'Mood Journal',src:require('../../../assets/images/techniqueBackgrounds/journal.jpg')},
{button: 'Meditation',src:require('../../../assets/images/techniqueBackgrounds/meditation.jpg')},
{button: 'ABCD',src:require('../../../assets/images/techniqueBackgrounds/abcd.jpg')},
{button: 'Optimism',src:require('../../../assets/images/techniqueBackgrounds/optimism1.jpg')},
{button: 'Journal',src:require('../../../assets/images/techniqueBackgrounds/journal.jpg')},
{button: 'Motivation',src:require('../../../assets/images/techniqueBackgrounds/motivation.jpg')},
{button: 'Defusion',src:require('../../../assets/images/techniqueBackgrounds/defusion.jpg')},
{button: 'Values',src:require('../../../assets/images/techniqueBackgrounds/goals.jpg')},
{button: 'Goals',src:require('../../../assets/images/techniqueBackgrounds/values.jpg')},
{button: 'Thought Record',src:require('../../../assets/images/techniqueBackgrounds/thought.jpg')},
{button: 'Breathe',src:require('../../../assets/images/techniqueBackgrounds/breathe.jpg')},
];
return (
<>
<StatusBar
backgroundColor={'#F5F5F5'}
translucent={false}
barStyle={'dark-content'}
/>
<Box style={styles.MainBox}>
<ScrollView>
<Box style={{height: '6%', alignItems: 'center'}}>
<Text style={styles.stepperTxt}>Create Habit</Text>
</Box>
<IconCircleBack
onPress={() => setHabitNavigation(0)}
style={{...styles.iconBack, top: '2.2%'}}
/>
<Box style={styles.choosenBox}>
<Box
style={styles.choosenButton}>
<Text style={{fontSize: 15, color: '#5D535C'}}>
{chooseSpan.but}
</Text>
</Box>
{chooseButton !== undefined ? (
<Box
style={styles.choosenButtonDynamic}>
<Text style={{fontSize: 15, color: '#5D535C'}}>
{techniques}
</Text>
</Box>
) : (
''
)}
</Box>
<Box style={{height: '6%', marginTop: '2%'}}>
<Text style={styles.headTxt}>Choose a technique</Text>
<Text
style={styles.subHeading}>
Create a habit from any one of your susbcribed techniques
</Text>
</Box>
<Box style={{height: 1050}}>
<Box style={{alignItems: 'center'}}>
{techniqueChooser.map((data, i) => {
return (
<TouchableHighlight
key={i}
underlayColor={'none'}
onPress={() => {
setChooseButton(i), setTechniques(data.button);
}}
style={styles.cardTechniques}>
<>
{chooseButton === i ? <IconCheck style={{position:'absolute',right:10,bottom:"10%",zIndex:1}} /> : ""}
<Image
style={styles.imageOptimism}
resizeMethod="scale"
resizeMode="cover"
source={data.src}
/>
<Image
style={{
...styles.imageBackdrop,
display: `${chooseButton === i ? 'none' : 'flex'}`,
}}
resizeMethod="scale"
resizeMode="cover"
source={require('../../../assets/images/techniqueBackgrounds/backdrop.png')}
/>
<Box
style={styles.buttonTechnique}>
<Text
style={{
fontSize: 14,
fontWeight: 'bold',
color: '#5D535C',
}}>
{data.button}
</Text>
</Box>
</>
</TouchableHighlight>
);
})}
</Box>
</Box>
</ScrollView>
<Box
style={{
position: 'absolute',
bottom: '3%',
width: '100%',
alignItems: 'center',
}}>
<Button
isDisabled={chooseButton !== undefined ? false : true}
style={{
...styles.button2,
backgroundColor: `${
chooseButton !== undefined ? '#36A2D0' : '#6D7A82'
}`,
}}
isLoadingText="Continue"
spinnerPlacement="end"
onPress={() =>{techniques === "Meditation" ? setHabitNavigation(4) : techniques === 'Breathe' ? setHabitNavigation(6) : setHabitNavigation(3)}}>
<MaterialIcons
name="arrow-forward-ios"
style={{
fontSize: 20,
color: `${chooseButton !== undefined ? 'white' : 'black'}`,
}}
/>
</Button>
</Box>
</Box>
</>
);
}
My app displays images and other info getting data from a JSON, and I want to set a blurRadius on the selected image when the unblur function is called.
My code is the following:
const [blur, setBlur] = useState(160);
const unblur = () => {
if(blur == 160){
setBlur(0);
}
}
{isLoading ? <ActivityIndicator/> : (
<FlatList
data={data}
keyExtractor={({ id }, index) => id}
renderItem={({ item }) => (
<>
<Text style={{ textAlign: "left", color: 'white', fontSize: 24 }}>
<Image style={{ alignSelf: "center" }} source={{uri: item.profile_picture, width: 48, height: 48}} />
{item.username}
</Text>
<TouchableOpacity onPress={() => unblur()}>
<Image style={{ alignSelf: "center" }} blurRadius={blur} source={{uri: item.picture, width: 400, height: 320}} />
</TouchableOpacity>
<Text style={{ textAlign: "left", color: 'white', fontSize: 24 }}>
ID {item.id}
</Text>
<Text>
{'\n'}{'\n'}
</Text>
</>
)}
/>
)}
I want to change the {blur} value for a given image when I tap the TouchableOpacity component of the image I want to unblur. Right in this moment when I tap an image, all the images in the list are getting unblurred.
You should add the blur values inside your items like this. Create a new components called Items. Then, add the blur state inside it. (not inside Main).
const Main = () => {
if (isLoading) {
return;
<ActivityIndicator />;
}
return (
<FlatList
data={data}
keyExtractor={({ id }, index) => id}
renderItem={({ item }) => <Item item={item} />}
/>
);
};
const Item = ({ item }) => {
const [blur, setBlur] = useState(160);
const unblur = () => {
if (blur == 160) {
setBlur(0);
}
};
return (
<>
<Text style={{ textAlign: "left", color: "white", fontSize: 24 }}>
<Image
style={{ alignSelf: "center" }}
source={{ uri: item.profile_picture, width: 48, height: 48 }}
/>
{item.username}
</Text>
<TouchableOpacity onPress={() => unblur()}>
<Image
style={{ alignSelf: "center" }}
blurRadius={blur}
source={{ uri: item.picture, width: 400, height: 320 }}
/>
</TouchableOpacity>
<Text style={{ textAlign: "left", color: "white", fontSize: 24 }}>
ID {item.id}
</Text>
<Text>
{"\n"}
{"\n"}
</Text>
</>
);
};
Also, may I suggest you can use 'onPressIn'. That way, image will unblur when the finger tap the image, not press the image. But that was your decision.
The code below creates a card, within this card I want to load the url from the card and make a webview appear using the 'react-native-webview' import.
import {View, Linking, TouchableNativeFeedback} from 'react-native';
import {Text, Button, Card, Divider} from 'react-native-elements';
import moment from 'moment';
import {WebView} from 'react-native-webview';
export default class DataItem extends React.Component {
render() {
const {title, description, publishedAt, source, urlToImage, url} =
this.props.article;
const {noteStyle, featuredTitleStyle} = styles;
const time = moment(publishedAt || moment.now()).fromNow();
return (
<TouchableNativeFeedback
useForeground
onPress={() => <WebView source={{uri: url}} style={{marginTop: 20}} />}>
<Card>
<Text style={{fontWeight: 'bold'}}> {title || 'YEET'} </Text>
<Divider style={{backgroundColor: '#dfe6e9', margin: 5}} />
<Card.Image source={{uri: urlToImage}} />
<Text style={{marginBottom: 10}}>{description || 'Read More..'}</Text>
<Divider style={{backgroundColor: '#dfe6e9'}} />
<View style={{flexDirection: 'row', justifyContent: 'space-between'}}>
<Text style={noteStyle}>{source.name.toUpperCase()}</Text>
<Text style={noteStyle}>{time}</Text>
</View>
</Card>
</TouchableNativeFeedback>
);
}
}
I assume you are trying to show a webview when the card press. The problem I see in your code is that you are trying to return a component on Touchable onPress which is not a correct way. You have to keep the state for that like when you press the card state goes active and shows the webview.
Try This
import { View, Linking, TouchableNativeFeedback } from 'react-native';
import { Text, Button, Card, Divider } from 'react-native-elements';
import moment from 'moment';
import { WebView } from 'react-native-webview';
export default class DataItem extends React.Component {
state = {
showWebview: false,
};
render() {
const {
title,
description,
publishedAt,
source,
urlToImage,
url,
} = this.props.article;
const { noteStyle, featuredTitleStyle } = styles;
const time = moment(publishedAt || moment.now()).fromNow();
return (
<View>
<TouchableNativeFeedback
useForeground
onPress={() => {
this.setState({ showWebview: true });
}}
>
<Card>
<Text style={{ fontWeight: 'bold' }}> {title || 'YEET'} </Text>
<Divider style={{ backgroundColor: '#dfe6e9', margin: 5 }} />
<Card.Image source={{ uri: urlToImage }} />
<Text style={{ marginBottom: 10 }}>
{description || 'Read More..'}
</Text>
<Divider style={{ backgroundColor: '#dfe6e9' }} />
<View
style={{ flexDirection: 'row', justifyContent: 'space-between' }}
>
<Text style={noteStyle}>{source.name.toUpperCase()}</Text>
<Text style={noteStyle}>{time}</Text>
</View>
</Card>
</TouchableNativeFeedback>
{this.state.showWebView && ( // it will show webview whew showWebview is true.
<WebView source={{ uri: url }} style={{ marginTop: 20 }} />
)}
</View>
);
}
}
Hey guys I'm having an issue with navigation:
I select an item from the menuoption
I then call the 'testFunction'
Function will call an alert function so it is working
When I add the navigation part I get the error below:
undefined is not an object (evaluating '_this2.props.navigation.navigate')
Here is the import code:
import { NavigationScreenProp } from "react-navigation";
Here is where it is added to props:
interface NotificationDropdownProps {
navigation: NavigationScreenProp<any,any>
}
Here is where code is rendered:
class NotificationDropdown extends React.Component<Props, NotificationDropdownState> {
testFunction = () => {
this.props.navigation.navigate('Leagues')
};
<MenuOption
onSelect={() =>
{
if(notification.type == INotificationType.SYSTEM){
this.testFunction()
}
}
}
customStyles={{ optionWrapper: { padding: 0, margin: 0, zIndex: 100000000 } }}>
<View style={[styles.notificationContainer]} >
<View style={styles.iconArea}>
<View style={[styles.iconCircle]}>
<Icon name={this.getIconType(notification.type)}
color={this.notificationColor(notification.type)} size={26} />
</View>
</View>
<View style={styles.notificationData} >
<Text style={styles.notificationTxt}>{notification.text}</Text>
<Text style={styles.notificationDate}>{this.getDate(new Date(notification.dateCreated))}</Text>
</View>
</View>
</MenuOption>
Render:
render() {
return (
<Menu
renderer={Popover} rendererProps={{ placement: 'bottom', preferredPlacement: 'bottom' }}
opened={this.state.opened}
onBackdropPress={() => this.togglePopup()}
onClose={() => {
this.setState({ showEmpty: true });
// Store.dispatch(SetNotificationSeen());
}}
onOpen={() => {
Store.dispatch(SetNumberSeen(this.props.notifications.length));
}}
>
<MenuTrigger onPress={() => this.togglePopup()}>
<View style={{ padding: 10 }}>
<Icon name='ios-notifications-outline' color={'rgba(0,0,0,0.6)'} size={25} /></View>
</MenuTrigger>
<MenuOptions customStyles={{
optionsContainer: {
width: Dimensions.get('window').width * 0.75,
zIndex: 100000000,
elevation: 8,
borderRadius: 20
}
}}>
<View style={{ padding: 10 }}>
<Text style={{
fontSize: 20,
marginLeft: 10,
color: 'rgba(0,0,0,0.6)',
fontWeight: 'bold',
paddingBottom: 5
}}>Notifications</Text>
{this.props.notifications.length > 0 ? <FlatList
contentContainerStyle={{ borderRadius: 10 }}
// only allow 5 notifications
data={this.props.notifications.slice(0,5)}
renderItem={({ item }) => this.renderNotification(item)}
style={{ maxHeight: 200, zIndex: 5 }}
keyExtractor={this.keyExtractor}
/> : <Text style={styles.noNotifications}>No Notifications!</Text>}
</View>
</MenuOptions>
</Menu>
);
}
What am I missing? any help is welcome
Here is where the is called from the header.tsx
<View style={styles.icon}>
<NotificationDropdown />
{this.props.numberSeen < this.props.notificationCount ? <Badge value={this.props.notificationCount - this.props.numberSeen > 99 ? '99+' : this.props.notificationCount - this.props.numberSeen}
status="error" containerStyle={styles.badge} /> : null}
</View>
Ok so it seems that NavigationDropDown doesn't have the navigation props.
What you need is to pass the navigation props explicitly as it is not a screen component.
in the headercomponent.tsx
<View style={styles.icon}>
<NotificationDropdown navigation={this.props.navigation} />
{this.props.numberSeen < this.props.notificationCount ? <Badge value={this.props.notificationCount - this.props.numberSeen > 99 ? '99+' : this.props.notificationCount - this.props.numberSeen}
status="error" containerStyle={styles.badge} /> : null}
</View>
I assume that you have the navigation props in the headercomponent.tsx
in my program write in react native i have this snippet:
getCompanyFunction() {
const { enterprises, navigation } = this.props;
return (
<ScrollView horizontal>
<View style={{ display: 'flex', flexDirection: 'row', flexWrap: 'nowrap' }}>
{ enterprises.map((enterprise) => {
return (
<Card key={enterprise.id} containerStyle={{ width: Dimensions.get('window').width - 50 }}>
<ListItem
title={enterprise.name}
subtitle={(
<View>
<Text style={{ color: theme.text.default }}>
{enterprise.fonction}
</Text>
<Text style={{ color: theme.palette.text.default }}>
{enterprise.location || ''}
</Text>
</View>
)}
onPress={enterprise.id && (() => handleItemPress(enterprise.id, navigation))}
/>
</Card>
);
})}
</View>
</ScrollView>
);
}
for my example i have three enterprise but only the first is apparent in the result. However the map function should iterate my array?
thank!
The map function returns a new array with the results of its operation.
MDN docs:
The map() method creates a new array with the results of calling a provided function on every element in the calling array.
You could use a FlatList component to render the resulting array from your map function.
Here's an example on how you could do it (assuming you don't need to alter enterprises data):
renderCard = (enterprise) => {
return (
<Card key={enterprise.id} containerStyle={{ width: Dimensions.get('window').width - 50 }}>
<ListItem
title={enterprise.name}
subtitle={(
<View>
<Text style={{ color: theme.text.default }}>
{enterprise.fonction}
</Text>
<Text style={{ color: theme.palette.text.default }}>
{enterprise.location || ''}
</Text>
</View>
)}
onPress={enterprise.id && (() => handleItemPress(enterprise.id, navigation))}
/>
</Card>
);
}
getCompanyFunction()
const { enterprises, navigation } = this.props;
return (
<ScrollView horizontal>
<View style={{ display: 'flex', flexDirection: 'row', flexWrap: 'nowrap' }}>
<FlatList
data={enterprises}
renderItem={({ item }) => renderCard(item)} />
</View>
</ScrollView>
);
}
You don't necessarily need to use a component to render a list of components, but it's usually the best course of action to do so.