Setting source of <Image/> with variable - javascript

I am trying some react native code which is as follows , I want to set the static images to an image view as follows but it doesn't load
const items = [
{ name: './images/home.png', code: '#1abc9c' }, { name: './images/home.png', code: '#2ecc71' },
{ name: './images/home.png', code: '#3498db' }, { name: './images/home.png', code: '#9b59b6' }
];
return (
<ImageBackground
source={require('./images/marble.jpg')}
style={styles.backgroundImage}>
<GridView
itemDimension={130}
items={items}
style={styles.gridView}
renderItem={item => (
<View style={[styles.itemContainer, { backgroundColor: item.code }]}>
<Image source={require(item.name)}></Image>
</View>
)}
/>
</ImageBackground>
);
Error I get is
calls to require expect exactly 1 string literal argument, but this was found: require(item.name).
Ofcourse I am new to react native so kindly ignore my missed terminology

You try like this
const items = [{ name: require('./images/home.png'), code: '#1abc9c' },{...}]
then
<Image source={item.name}></Image>

Related

Changing values in a dropdown menu

I'm working with a custom dropdown menu in React Native and am having a problem changing the text when trying to reuse the dropdown in other components.
DropdownMenu.js
export const DropdownMenu = ({dropdownMenuItems}) => {
const [isActive, setIsActive] = React.useState(false);
const onPress = () => {
setIsActive(!isActive);
};
return (
<TouchableOpacity
activeOpacity={1}
onPress={() => setIsActive(false)}
style={{flex: 1}}>
<View>
<TouchableOpacity style={styles.img} onPress={onPress}>
<Image style={styles.imgimg} source={require('./icon.png')} />
</TouchableOpacity>
<Animated.View
style={{
...styles.menu,
opacity: fadeAnim,
transform: [{translateY: translateAnim}],
}}
pointerEvents={isActive ? 'auto' : 'none'}>
<FlatList
data={dropdownMenuItems}
renderItem={({item, index}) => (
<OpenURLButton
url={item.href}
label={item.name}
style={
index === 0
? {borderTopLeftRadius: 8, borderTopRightRadius: 8}
: index === dropdownMenuItems.length - 1
? {borderBottomLeftRadius: 8, borderBottomRightRadius: 8}
: {}
}
/>
)}
/>
</Animated.View>
</View>
</TouchableOpacity>
);
};
In the CompactMenu component, I import my <DropdownMenu /> and set my initial values for my menu:
CompactMenu.js
import React from 'react';
import {SafeAreaView} from 'react-native';
import {DropdownMenu} from './DropdownMenu';
const CompactMenu = () => {
const backgroundStyle = {
backgroundColor: '#fff',
flex: 1,
display: 'flex',
};
const dropdownMenuItems = [
{name: 'Messages', href: '/messages'},
{name: 'Trips', href: '/trips'},
{name: 'Saved', href: '/saved'},
];
return (
<SafeAreaView style={backgroundStyle}>
<DropdownMenu dropdownMenuItems={dropdownMenuItems} />
</SafeAreaView>
);
};
export default CompactMenu;
After importing <CompactMenu /> into another component, I try to change the name & the href in object:
example import:
<CompactMenu dropdownMenuItems={[{name: "changed name", href: "/somePath"}]} />
However, the same strings from CompactMenu.js are displayed in the dropdown.
Being new to RN, I'm not sure of two things here.
1.) Why do the text value for "name" not change when used in a different component?
2.) Shouldn't navigation to another screen use { navigation } instead of href:? I've tried adding onPress={() => navigation.navigate('SomeScreen') in the href but I get an error.
I'm not sure what the correct solution to this is. Any help would be appreciated.
You are not using the props dropdownMenuItems that you are passing to CompactMenu. Instead, you reuse the same menu items for the DropdownMenu component everytime you create a CompactMenu.
You need to use the props that you are passing. I have kept the static items as a default value. If you would like to have these items as well and to add additional items via props, then have a look at the second solution.
Notice that I have integrated some small changes to the rest of the code as well.
const defaultItems = [
{name: 'Messages', href: '/messages'},
{name: 'Trips', href: '/trips'},
{name: 'Saved', href: '/saved'},
];
const CompactMenu = ({dropdownMenuItems = defaultItems}) => {
return (
<SafeAreaView style={styles.backgroundStyle}>
<DropdownMenu dropdownMenuItems={dropdownMenuItems} />
</SafeAreaView>
);
};
const styles = StyleSheet.create({
backgroundStyle: {
backgroundColor: '#fff',
flex: 1,
}
});
Now using the CompactMenu component can receive dropdownMenuItems and will pas them to the DropdownMenu component.
<CompactMenu dropdownMenuItems={[{name: "changed name", href: "/somePath"}]} />
If you want to keep default items and add additional items via props, we could achieve this by merging the provided props with our default items.
const defaultItems = [
{name: 'Messages', href: '/messages'},
{name: 'Trips', href: '/trips'},
{name: 'Saved', href: '/saved'},
];
const CompactMenu = ({dropdownMenuItems}) => {
return (
<SafeAreaView style={styles.backgroundStyle}>
<DropdownMenu dropdownMenuItems={[...defaultItems, ...dropdownMenuItems]} />
</SafeAreaView>
);
};
Your second questions addresses the react-navigation framework for react-native. This is a very broad topic and I am assuming from your question that you don't know how this works yet, since you have not setup the necessary structure for using it. I encourage you to go through the documentation first.
In summary, you will need to define a navigator, e.g. a stack-navigator and add a name reference for each of your screens to the dropdown menu. To keep things short, here is a minimal example on how this could work.
const MenuScreen1 = (props) {
return (...)
}
const MenuScreen2 = (props) {
return (...)
}
const CompactMenu = ({dropdownMenuItems, navigation}) => {
return (
<SafeAreaView style={styles.backgroundStyle}>
<DropdownMenu dropdownMenuItems={dropdownMenuItems} navigation={navigation} />
</SafeAreaView>
);
};
const dropdownMenuItems = [
{name: 'Menu Item 1', screen: 'Item1'},
{name: 'Menu Item 2', screen: 'Item2'},
]
const Home = ({navigation}) {
return <CompactMenu navigation={navigation} dropdownMenuItems={dropdownMenuItems} />
}
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Item1" component={MenuScreen1} />
<Stack.Screen name="Item2" component={MenuScreen2} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
Notice that I have created two screens whose names, which I have defined in the stack navigator, are provided to the CompactMenu. Notice as well that the navigation framework will pas the navigation object only to components that are defined as a screen, thus I have decided to pass the navigation object to the CompactMenu and the DropdownMenu component. You can use the useNavigation hook if you prefer this method.
Now, in your DropdownMenu you can navigate on click to the defined screens.
export const DropdownMenu = ({dropdownMenuItems, navigation}) => {
const [isActive, setIsActive] = React.useState(false);
const onPress = () => {
setIsActive(!isActive);
};
return (
<TouchableOpacity
activeOpacity={1}
onPress={() => setIsActive(false)}
style={{flex: 1}}>
<View>
<TouchableOpacity style={styles.img} onPress={onPress}>
<Image style={styles.imgimg} source={require('./icon.png')} />
</TouchableOpacity>
<Animated.View
style={{
...styles.menu,
opacity: fadeAnim,
transform: [{translateY: translateAnim}],
}}
pointerEvents={isActive ? 'auto' : 'none'}>
<FlatList
data={dropdownMenuItems}
renderItem={({item, index}) => (
<Button
onPress={() => navigation.navigate(item.screen)}
title={item.name}
style={
index === 0
? {borderTopLeftRadius: 8, borderTopRightRadius: 8}
: index === dropdownMenuItems.length - 1
? {borderBottomLeftRadius: 8, borderBottomRightRadius: 8}
: {}
}
/>
)}
/>
</Animated.View>
</View>
</TouchableOpacity>
);
};

The text isn't displaying on expo app. I think the prop is not being passed properly. How should I correct that?

The component file:
{ return (
<TouchableOpacity /* onLongPress={onLongPress} style={[styles.card, backgroundColor]} */>
<View style={styles.fixToText}>
<Text style={styles.title}>{item.post_title}</Text>
<MaterialCommunityIcons
name="star-outline"
size={24}
color="black"/>
</View>
<Text style={styles.tasks}>{item.post_info}</Text>
<View style={styles.fixToText}>
<Text style={styles.time}>{item.time}</Text>
</View>
</TouchableOpacity>
);
}
App.js file
const App = () => {
const [tasks,setTasks]= useState([
{
id: 1,
post_title: "NEW Task",
post_info: "Assigned with the ID",
time: "1 min ago",
},
{
id: 2,
post_title: "NEW Task",
post_info: "Assigned with the ID",
time: "1 min ago",
},
]);
return (
<>
<Notification task={tasks}/>
</>
);
}
I am sure that the props are not being properly passed. Where exactly is it wrong ? I have passed it from App to Component file using {task} . I can only see the star icon though displayed at the side.
Are you able to attach the whole component?
it seems like the name should be either props.task[i].post_title
or in case you destruct the props using const {task}=props it should be task[i].post_title

Flatlist and data-mapping didn't show data

I tried to map my data using array.prototype.map() but the data merges into one line, and I tried using flatlist as alternative but it doesn't show anything..... Can someone help me?
const array = [
{name: 'Almer', id: 1},
{name: 'Donat', id: 2},
{name: 'Ardi', id: 3},
];
above is the data
{array.map((e) => {
return (
<View>
<Text>{e.name}</Text>
</View>
);
})}
Any Help or reference will save my day! Thank You
Tried with no error:
Code:
import React from "react";
import { Text, SafeAreaView, View, FlatList } from "react-native";
const array = [
{ name: 'Almer', id: 1 },
{ name: 'Donat', id: 2 },
{ name: 'Ardi', id: 3 },
];
const Test = () => {
return (
<SafeAreaView>
<Text>--- array with map ---</Text>
{array.map((e) => {
return (
<View>
<Text>{e.name}</Text>
</View>
);
})}
<Text>--- FlatList --- </Text>
<FlatList
data={array}
renderItem={({ item }) => (
<View>
<Text>{item.name}</Text>
</View>
)}
keyExtractor={item => item.id.toString()}
/>
</SafeAreaView>
)
};
export default Test;
And snack for furthur changes: Expo example

the library "react-native-snap-carousel" is not processing the card image

I am new in react native and I was trying to use the "react-native-snap-carousel". The carousel is working with the parameters in the "carouselItems" variable as I sent, but the image is not working. I supoused to place it at the Card as a background image, with a short description with the same parameter array, but it is not working.
Can anyone help me to set it?
the array used to fill the cards:
const carouselItems = [
{
title: "Doce",
text: "[TEXTO DESCRITIVO]",
thumbnail: "assets/splash.png",
},
{
title: "Salgado",
text: "[DESCRIÇÃO]",
thumbnail: "assets/splash.png",
},
]
the folder structure is:
homemade-app / assets / splash.png
return (
<View style={styles.item}>
<ParallaxImage
source={{ uri: item.thumbnail }}
containerStyle={styles.imageContainer}
style={styles.image}
parallaxFactor={0.2}
{...parallaxProps}
/>
{item.thumbnail}
<Text style={styles.title} numberOfLines={2}>
{item.title}
</Text>
</View>
)
}
const goForward = () => {
carouselRef.current.snapToNext();
};
return (
<View style={styles.container}>
<TouchableOpacity onPress={goForward}>
<Text>go to next slide</Text>
</TouchableOpacity>
<Carousel
layout={"default"}
ref={ref => carousel = ref}
data={carouselItems}
sliderWidth={screenWidth}
sliderHeight={screenWidth}
itemWidth={screenWidth - 60}
renderItem={renderItem}
onSnapToItem={index => setState({ activeIndex: index })}
hasParallaxImages={true} />
</View>
);
}
I saw the article about how to handle local file with assets, but I still could not make it work properly.
Link to the article: (https://dev.to/fdefreitas/how-to-obtain-a-uri-for-an-image-asset-in-react-native-with-expo-7bm)
If you are using expo. First of all try with a static route remember you need full path not assets/myimage this is wrong, because sometime use it from array give problems like in this question Render images sources from parsed array of objects in react native .
array
const carouselItems = [
{
title: "Doce",
text: "[TEXTO DESCRITIVO]",
thumbnail: require("./../assets/splash.png"),
},
{
title: "Salgado",
text: "[DESCRIÇÃO]",
thumbnail: require("./../assets/splash.png"),
},
]
<ParallaxImage
source={require('#expo/snack-static/yourimage.png')}
...
/>
or put your image in same folder
<ParallaxImage
source={require('./your-image.png')}
...
/>

Nested map cannot render <Text> element from main loop

I have a nested array of "credits"
const credits = [
{
id: 1,
heading: 'Test Organisation',
credits: [
{id: 1, text: 'Joe Bloggs'},
{id: 2, text: 'Jane Bloggs'},
]
},
....
];
I am wanting to print each "header" in a <Text> element, and then subsequently each of their "credits" in a <Text> element.
I have looked at the following already answered questions on how to achieve this, but one is for ReactJS and uses HTML and the other that uses React Native outputs only the opening tag of a view:
Cannot Render Nested Maps In ReactJS
How to use if else condition inside nested map function in react-native?
I am being told there is a syntax error as it is expecting a close parentheses after the end of the first <Text> element.
Here is what I have:
render() {
return (
<ScrollView style={styles.container}>
<View style={styles.centredHighlightHeaderWrapper}>
<Text style={styles.centredHighlightHeader}>
Credits
</Text>
</View>
{
credits.map(item => (
<Text style={styles.centredHeader}>{item.heading}</Text>#Unexpected token -- js error says expecting "," - phpstorm says expecting ")"
{
item.credits.map(credit => (
<Text style={styles.name}>{credit.text}</Text>
))
}
))
}
</ScrollView>
);
}
{
credits.map(item => (
<React.Fragment>
<Text style={styles.centredHeader}>{item.heading}</Text>
{
item.credits.map(credit => (
<Text style={styles.name}>{credit.text}</Text>
))
}
</React.Fragment>
))
}
You can't have adjacent react elements without a container. So I've put them both in a React.Fragment for you

Categories