import React from "react";
import { View, Text, StyleSheet, ScrollView, Image } from "react-native";
const Icons = [
{ name: "Food", uri: require("./images/Food.png") },
{ name: "Mart", uri: require("./images/mart.png") },
{ name: "Car", uri: require("./images/car.png") }
];
const IconSelection = Icons.map((icons) => (
<View>
<Image source={icons.uri} />
<Text style={{ textAlign: "center" }}>{icons.name}</Text>
</View>
));
const styles = StyleSheet.create({});
export default IconSelection;
IconSelection.js
How do I add images inside my const Icons? Basically I want to create like a list of Icons using images and able to call them. Previously my method is basically handcode them but I found it is very messy. I think maps() could help me but I'm not really sure how to use it too. Thank you.
IconSelectionis a reference to an array containing returned JSX.
Convert it into a functional component
import React from "react";
import { View, Text, StyleSheet, ScrollView, Image } from "react-native";
const Icons = [
{ name: "Food", uri: require("./images/Food.png") },
{ name: "Mart", uri: require("./images/mart.png") },
{ name: "Car", uri: require("./images/car.png") },
];
const IconSelection = () =>
Icons.map((icons) => (
<View>
<Image source={icons.uri} />
<Text style={{ textAlign: "center" }}>{icons.name}</Text>
</View>
));
const styles = StyleSheet.create({});
export default IconSelection;
Related
I would like to create a list from an array using getParam (transfer data between screens).
The end result should look like this:
Wiosła
Deska
Podciąganie
now I'm using Text, probably it can be work by FlatList (but nothing is displayed)
code:
import React, {useState} from "react";
import { Button, StyleSheet, Text, View, Pressable, FlatList, TouchableOpacity } from 'react-native';
import { globalStyles } from "../styles/global";
export default function PlanList({navigation}){
const [training, setTraining] = useState([
{ title: 'Trening pleców', body: ['wiosła', 'deska', 'podciaganie'], key: '1' },
{ title: 'Trening brzuch/uda/pośladki', body: ['odwodzenie', 'krab', 'martwy ciąg'], key: '2' },
{ title: 'Trening ręce+klatka', body: ['rozpiętki', 'przyciąganie do skroni', 'bicek'], key: '3' },
]);
return(
<View style={globalStyles.container}>
<Text>Ułóż swoje bloki treningowe</Text>
<Pressable><Text>Dodaj nowy</Text></Pressable>
<FlatList
data={training}
renderItem={({item}) => (
<TouchableOpacity style={globalStyles.trainingGrup} onPress={() => navigation.navigate('Training', item)}>
<Text>{item.title}</Text>
</TouchableOpacity>
)}
></FlatList>
</View>
)
}
import React from "react";
import { StyleSheet, View, Text, Image, FlatList } from "react-native";
import { globalStyles , images} from "../styles/global";
export default function Training({navigation}){
return(
<View style={globalStyles.container}>
<Text>
{navigation.getParam('body')}
</Text>
</View>
)
}
If you can access the data in the Training screen
you should declare a const
const { title } = route.params;
Been using Expo and RN on an app, but I'm stuck with a problem. I'm using Expo Video
to make a photo/video gallery. The problem is, if I have more than 1 video in the array, only the last one will play (problem with useRef). And I couldn't find a way to create a ref for each one of them.
Solutions that I've tried and half worked: I created a VideoComponent (as a function then added on return), and each component had its own useRef and useState for playing inside the component a different useRef/useState for video/status for each. It worked okay-ish. But the problem was when other states changed (user presses like, for example). Whenever a state changes, and rerenders, the whole video reset to the beginning. Which is not ok.
The video reset on state change of other components doesn't affect the video if doing it normally (one useRef/state) but as I said, It's only playing the last component, which is not okay.
import React, { useRef, useState } from 'react';
import {
SafeAreaView,
View,
FlatList,
StyleSheet,
Text,
StatusBar,
} from 'react-native';
function App(props) {
const [allData, setAllData] = useState([
{
medias: [
{ link: 'https://link.com/link1.avi', mediaExtension: 'avi' },
{ link: 'https://link.com/link2.jpg', mediaExtension: 'jpg' },
{ link: 'https://link.com/link3.mov', mediaExtension: 'mov' },
],
name: 'Name',
description: 'description',
},
]);
const video = useRef(null);
const [status, setStatus] = useState({});
return (
<View style={{}}>
<FlatList
horizontal
data={allData}
renderItem={({ item }) => (
<View style={{}}>
{item.medias.map((item) => (
<View>
{item.mediaExtension === 'mov' || 'avi' || 'WebM' ? (
<View style={{ flex: 1 }}>
<TouchableOpacity
onPress={() =>
video.isPlaying
? video.current.pauseAsync()
: video.current.playAsync()
}>
<Video
ref={video}
style={{ alignSelf: 'center' }}
source={{
uri: item.link,
}}
onPlaybackStatusUpdate={(status) =>
setStatus(() => status)
}
/>
</TouchableOpacity>
</View>
) : (
<Image style={{}} source={{ uri: item.link }} />
)}
</View>
))}
</View>
)}
/>
</View>
);
}
export default App;
As far as I understand, you want to create a FlatList of Videos, and onScroll you want to pause it. This can be implemented as shown below
Also, here is a Working Example for this
import * as React from 'react';
import { Text, View, StyleSheet, FlatList } from 'react-native';
import Constants from 'expo-constants';
import VideoPlayer from './components/VideoPlayer';
const Videos = [
{
_id: 1,
source: require('./assets/videoplayback.mp4'),
},
{
_id: 2,
source: require('./assets/videoplayback.mp4'),
},
{
_id: 3,
source: require('./assets/videoplayback.mp4'),
},
{
_id: 4,
source: require('./assets/videoplayback.mp4'),
},
{
_id: 5,
source: require('./assets/videoplayback.mp4'),
},
{
_id: 6,
source: require('./assets/videoplayback.mp4'),
},
];
export default function App() {
const [Viewable, SetViewable] = React.useState([]);
const ref = React.useRef(null);
const onViewRef = React.useRef((viewableItems) => {
let Check = [];
for (var i = 0; i < viewableItems.viewableItems.length; i++) {
Check.push(viewableItems.viewableItems[i].item);
}
SetViewable(Check);
});
const viewConfigRef = React.useRef({ viewAreaCoveragePercentThreshold: 80 });
return (
<View style={styles.container}>
<FlatList
data={Videos}
keyExtractor={(item) => item._id.toString()}
renderItem={({ item }) => <VideoPlayer {...item} viewable={Viewable} />}
ref={ref}
onViewableItemsChanged={onViewRef.current}
viewabilityConfig={viewConfigRef.current}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
},
});
and VideoPLayer component looks like this
import * as React from 'react';
import { Text, View, StyleSheet, Dimensions } from 'react-native';
import Constants from 'expo-constants';
import { Video, AVPlaybackStatus } from 'expo-av';
export default function VideoPlayer({ viewable, _id, source }) {
const video = React.useRef(null);
React.useEffect(() => {
if (viewable) {
if (viewable.length) {
if (viewable[0]._id === _id) {
video.current.playAsync();
} else {
video.current.pauseAsync();
}
} else {
video.current.pauseAsync();
}
} else {
video.current.pauseAsync();
}
}, [viewable]);
return (
<View style={styles.container}>
<Video
ref={video}
source={source}
rate={1.0}
volume={1.0}
resizeMode={'contain'}
isLooping
shouldPlay
style={styles.video}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
width: Dimensions.get('window').width,
marginBottom: 100,
marginTop: 100,
},
video: {
width: Dimensions.get('window').width,
height: 300,
},
});
I am getting this error when I am trying to get the image path which is in the js object stored as a string with require() as a prop.
Warning: Failed prop type: Invalid prop `source` supplied to `Image`.
CategoriesScreen.js
import React from "react";
import {
View,
Text,
FlatList,
StyleSheet,
TouchableOpacity,
} from "react-native";
import { CATEGORIES } from "../Data/Dummy-Data";
import CategoryGrid from "../component/categoryGrid";
const CategoriesScreen = (props) => {
const renderGridItem = (itemData) => {
return (
<CategoryGrid
title={itemData.item.title}
imgUrl={itemData.item.url}
//console.log (itemData.item.url)-> require(..) ->image path
onSelect={() =>
props.navigation.navigate({
routeName: "CategoryMeals",
params: {
categoryId: itemData.item.id,
},
})
}
></CategoryGrid>
);
};
return (
<View>
<FlatList data={CATEGORIES} renderItem={renderGridItem} numColumns={2} />
</View>
);
};
CategoriesScreen.navigationOptions = {
headerTitle: "Meals Categories",
};
const styles = StyleSheet.create({
screen: {
flex: 1,
justifyContent: "center",
alignItems: "center",
//this is unused till now.
},
});
export default CategoriesScreen;
Here I have stored the path of all images
Dummy-data.js
import Category from "../Models/category";
export const CATEGORIES = [
new Category("C1", "Italian", "require('../assets/Images/italian.jpeg')"),
new Category("C2", "Indian", "require('../assets/Images/Indian.jpeg')"),
new Category("C3", "French", "require('../assets/Images/French.jpeg')"),
new Category(
"C4",
"Hamburgers",
"require('../assets/Images/Hamburgers.jpeg')"
),
new Category("C5", "German", "require('../assets/Images/German.jpeg')"),
new Category("C6", "Asian", "require('../assets/Images/Asian.jpeg')"),
new Category("C7", "Breakfast", "require('../assets/Images/Breakfast.jpeg')"),
new Category("C8", "Dinner", "require('../assets/Images/Dinner.jpeg')"),
];
category.js
class Category {
constructor(id, title, url) {
this.id = id;
this.title = title;
this.url = url;
}
}
export default Category;
CategoryGrid.js
import React from "react";
import {
TouchableOpacity,
StyleSheet,
View,
Text,
ImageBackground,
} from "react-native";
const CategoryGrid = (props) => {
return (
<TouchableOpacity style={styles.gridItems} onPress={props.onSelect}>
<View>
<ImageBackground
source={props.imgUrl}
style={{ width: "100%", height: "90%" }}
/>
<Text>{props.title}</Text>
</View>
</TouchableOpacity>
);
};
const styles = StyleSheet.create({
gridItems: {
flex: 1,
margin: 15,
height: 150,
},
});
export default CategoryGrid;
console.log() says in CategoriesScreen.js and in categoryGrid.js -> require(../assests/Images/image.jpeg)
I am trying to get the image path as a prop from CategoryScreen.js to categoryGrid.js which is stored as an object in Dummy-Data.js.
Any idea what I am doing wrong?
do it like this
<ImageBackground
source={{uri: props.imgUrl}}
style={{ width: "100%", height: "90%" }}
/>
import Category from "../Models/category";
export const CATEGORIES = [
new Category("C1", "Italian", require("../assets/Images/italian.jpeg")),
new Category("C2", "Indian", require("../assets/Images/Indian.jpeg")),
new Category("C3", "French", require("../assets/Images/French.jpeg")),
new Category("C4", "Hamburgers", require("../assets/Images/Hamburgers.jpeg")),
new Category("C5", "German", require("../assets/Images/German.jpeg")),
new Category("C6", "Asian", require("../assets/Images/Asian.jpeg")),
new Category("C7", "Breakfast", require("../assets/Images/Breakfast.jpeg")),
new Category("C8", "Dinner", require("../assets/Images/Dinner.jpeg")),
];
I am learning React native and was trying to build an app. However, the app is stuck on a white screen and doesn't show anything nor gives any error. This code is going to render a flatlist from an array and will have a delete to swipe button on the right. I am not getting any errors though.
Message.js
import React, { useState } from 'react'
import {
View,
Text,
StyleSheet,
FlatList,
SafeAreaView,
StatusBar,
ItemSeparatorComponent,
Platform
} from 'react-native'
import ListItem from '../components/ListItem'
import ListItemSeparator from '../components/ListItemSeparator'
import DeleteSwipe from '../components/DeleteSwipe'
const messages = [
{
id: 1,
name: 'T1',
description: 'D2',
image: require('../assets/mosh.jpg')
},
{
id: 2,
name: 'T2',
description: 'D2',
image: require('../assets/mosh.jpg')
},
{
id: 3,
name: 'T3',
description: 'D3',
image: require('../assets/mosh.jpg')
},
{
id: 4,
name: 'T4',
description: 'D4',
image: require('../assets/mosh.jpg')
}
]
export default function Message () {
const [messages, setMessage] = useState(messages)
const handleDelete = messages => {
const newMessages = messages.filter(m => m.id != messages.id)
setMessage(newMessages)
}
return (
<SafeAreaView style={styles.screen}>
<FlatList
data={messages}
keyExtractor={messages => messages.id.toString()}
renderItem={({ item }) => (
<ListItem
name={item.name}
description={item.description}
image={item.image}
onPress={() => console.log('touched', item)}
renderRightActions={() => (
<DeleteSwipe onPress={() => handleDelete(item)} />
)}
/>
)}
ItemSeparatorComponent={ListItemSeparator}
/>
<FlatList />
</SafeAreaView>
)
}
const styles = StyleSheet.create({
screen: {
padding: Platform.OS === 'android' ? StatusBar.currentHeight : 0
}
})
DeleteSwipe.js
import React from 'react'
import { View, Text, StyleSheet, TouchableWithoutFeedback } from 'react-native'
import Swipeable from 'react-native-gesture-handler/Swipeable'
import { AntDesign } from '#expo/vector-icons'
const DeleteSwipe = props => {
const { renderRightActions } = props
return (
<TouchableWithoutFeedback onPress={console.log('delete it')}>
<View style={styles.container}>
<AntDesign name='delete' size={24} color='white' />
</View>
</TouchableWithoutFeedback>
)
}
const styles = StyleSheet.create({
container: {
width: 70,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#ff5252'
}
})
export default DeleteSwipe
If it is a debugger issue, Restart the debugger if react native debugger is running. and again start
Or it could be a flexbox issue, Try to add or remove display: flex and flex:1 on this and parent.
Or it could be component is too small, Open inspector from dev menu and check component names in screen.
Change onPress={console.log....} to onPress={() => console.log(...
)}
But it seems what you want is onPress={props.onPress}
I was following tutorial and I got 'ReferenceError can't find variable flatlist' error, then I deleted the code and copied from the github to check if I might missed something and it's still didn't work.
import React, {useState} from 'react';
import {StyleSheet, Text, View,FlatList} from 'react-native';
import Header from './components/header';
export default function App () {
const [todos, setTodos] = useState([
{ text: 'buy coffee', key: '1' },
{ text: 'create an app', key: '2' },
{ text: 'play on the switch', key: '3' }
]);
return (
<View style={styles.container}>
<Header />
<View style={styles.content}>
{/* add todo form */}
<View style={styles.list}>
<FlatList
data={todos}
renderItem={({item}) => (
<Text>{item.text}</Text>
)}
/>
</View>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
content:{
padding: 40,
},
list:{
marginTop:20,
}
});
Header :
import React from 'react';
import {StyleSheet, Text, View} from 'react-native';
export default function Header() {
return(
<View style={styles.header}>
<Text style={styles.title}>My Todo List</Text>
</View>
)
}
const styles= StyleSheet.create({
header:{
height: 80,
paddingTop: 38,
backgroundColor: 'red',
},
title:{
textAlign: 'center',
color:'#fff',
fontSize: 20,
fontWeight:'bold',
}
});
export default Header;
Perhaps something changed in the version or something else. I will be grateful if you can tell how I can fix the error.
Edit: I changed the casing from Flatlist to FlatList and I got error 'Element type invalid: expected a string (for built- in components)'.
\ Screenshot
change case of Flatlist import as:
import {StyleSheet, Text, View,FlatList} from 'react-native';
check export of your header component. You have exported Header Component two time.
Try Replace Flatlist with FlatList
Correct: import {StyleSheet, Text, View,FlatList} from 'react-native';
Also, try to export as Class, if it's entry point:
import React, { Component } from 'react';
export default class App extends Component {
state = {
todos: [
{ text: 'buy coffee', key: '1' },
{ text: 'create an app', key: '2' },
{ text: 'play on the switch', key: '3' },
],
};
render() {
const { todos } = this.state;
return (
<View style={styles.container}>
<Header />
<View style={styles.content}>
{/* add todo form */}
<View style={styles.list}>
<FlatList
data={todos}
renderItem={({ item }) => <Text>{item.text}</Text>}
/>
</View>
</View>
</View>
);
}
}