import React, { Component } from "react";
import { StyleSheet, FlatList, View, Image, Text } from "react-native";
const n1 = require("../img/n1.png");
const n2 = require("../img/n2.png");
const n3 = require("../img/n3.png");
const n4 = require("../img/n4.png");
const n5 = require("../img/n5.png");
const n0 = require("../img/n0.png");
class Example extends Component {
constructor(props) {
super(props);
this.state = {
data: [
{ id: 1, image: n1, title: " n1 " },
{ id: 2, image: n2, title: " n2 " },
{ id: 3, image: n3, title: " n3" },
{ id: 4, image: n4, title: " n4 " },
{ id: 5, image: n5, title: " n5" },
],
};
}
render() {
return (
<FlatList
style={styles.container}
data={this.state.data}
keyExtractor={(item) => {
return item.id;
}}
renderItem={({ item }) => {
return (
<View style={styles.box}>
<View style={styles.info}>
<Text style={styles.name}>{item.title} </Text>
<Image style={styles.image} source={{ uri: item.image }} />
</View>
</View>
);
}}
/>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 30,
},
info: {
flex: 1,
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
},
image: {
width: 173,
height: 88,
},
title: {
color: "#707070",
opacity: 1,
},
box: {
marginLeft: -120,
marginTop: 10,
backgroundColor: "white",
flexDirection: "row",
marginBottom: 20,
},
});
This is part of the code that I have deleted some code not relevant to this question.
My question is how do I change all images(n1-n5) by one click to n0.
The page will show 5 different images(n1-n5) in a list, then after clicking a button, all images will be replaced by n0.
I got some idea about setState, but I am new to React and don't know how to make it work(or not state) even after search.
BTW, its a webpage, but I use react-native-web to get the images more pretty arranged.
This is a simple map operation.
handleClick = () =>
this.setState((prev) => ({
data: prev.data.map((item) => ({
...item,
image: n0,
title: "n0",
})),
}));
Start by adding extraData to the flat list to re render when button clicked
<FlatList
style={styles.container}
data={this.state.data}
extraData={this.state}
keyExtractor={(item) => {
return item.id;
}}
renderItem={({ item }) => {
return (
<View style={styles.box}>
<View style={styles.info}>
<Text style={styles.name}>{item.title} </Text>
<Image style={styles.image} source={{ uri: item.image }} />
</View>
</View>
);
}}
/>
....
//add function for button click:
onButtonClicked(){
//create the new data array
//replace it with the old array state
this.setState({data: new_data}); //flat list should re render when state changed
}
Related
I'm doing a project in react native and my ImageBackgroud component does not want to render. The odd thing is I am already using ImageBackground in another component and it works there. I tried resizing the image but that didn't help.
Here is my component that renders child component with ImageBackground:
const DuringStay = () => {
return (
<View style={styles.container}>
<FlatList
data={test}
numColumns={2}
columnWrapperStyle={{
justifyContent: 'space-between',
marginBottom: 15,
}}
keyExtractor={item => item.id}
renderItem={({ item }) => (
<DuringStayTile item={item} />
)}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
paddingHorizontal: 20,
flex: 1,
},
});
export default DuringStay;
Here is my component that doesn't want to render ImageBackground. My data comes correctly to the component and inside Pressable i can render other components but ImageBackground won't show up
const DuringStayTile = ({item}) => {
const { title, uri } = item;
console.log(title,uri)
return (
<Pressable style={styles.container}>
<ImageBackground source={uri} resizeMode="cover" style={styles.image}>
<LinearGradient
style={styles.textBox}
colors={['transparent','rgba(0,0,0,0.6)']}>
<Text>
{title}
</Text>
</LinearGradient>
</ImageBackground>
</Pressable>
);
};
export default DuringStayTile;
const styles = StyleSheet.create({
container: {
width: '48%',
padding: 20,
borderRadius: 10,
padding:60,
backgroundColor:'pink'
},
title: {
fontWeight: 'bold',
fontSize: 16,
},
image: {
flex: 1,
overflow:'hidden',
justifyContent:'center'
},
textBox:{
position:'absolute',
right:0,
bottom:0,
width:'100%'
},
});
Data that is imported:
export const test = [
{
uri:require('../assets/f1.jpg'),
title: 'Zip Line',
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba'
},
{
uri: require('../assets/during.jpeg'),
title: 'Blue Cave',
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
},
{
uri: require('../assets/post.jpg'),
title: 'Rafting',
id: '58694a0f-3da1-471f-bd96-145571e29d72',
}
]
image: {
flex: 1,
overflow:'hidden',
justifyContent:'center',
padding:30
},
I'm looking for someone that could help me just images in a flatlist grid.
I was able to get it working with text but not images in the assets folder.
I want to have separate images that will be stored in the assets folder to be in the boxes of the flatlist grid.
Please let me know if you need more information!
Here is the code:
import React from 'react';
import { View, Image, Text, StyleSheet, TouchableOpacity, FlatList, Dimensions } from 'react-native';
import { drawer } from '../navigation/AppNavigation';
import { hp, wp } from '../utils/responsiveScreen';
const dataList = [{ key: '1' }, { key: '2' }, { key: '3' }, { key: '4' }, { key: '5' },{ key: '6' },{ key: '6' },{ key: '6' }]
const numColums = 2
const WIDTH = Dimensions.get('window').width
const Main = () => {
formatData = (data, numColums) =>{
const totalRows = Math.floor(data.length / numColums)
let totalLastRow = dataList.length - (totalRows * numColums)
while(totalLastRow !== 0 && totalLastRow !== numColums){
dataList.push({'key': 'blank', empty: true})
totalLastRow++
}
return dataList
}
_renderItem = ({ item, index }) => {
let {itemStyle, itemText} = styles
if(item.empty){
return <View style={[itemStyle]}/>
}
return (
<View style={itemStyle}>
<Text style={styles.itemText}>{item.key}</Text>
</View>
)
}
return (
<View style={styles.container}>
<TouchableOpacity
style={{ height: 50 }}
onPress={() => drawer.current.open()}>
<Image source={require('../assets/menu.png')} />
</TouchableOpacity>
<Text style={styles.textStyle}>Stars</Text>
<FlatList
data={this.formatData(dataList, numColums)}
renderItem={this._renderItem}
keyExtractor={(item, index) => index.toString()}
numColumns = {numColums}
/>
</View>
);
};
And here is the Style sheet:
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
paddingTop: hp(7),
paddingHorizontal: wp(6),
},
textStyle: {
marginBottom: 20,
fontWeight: 'bold',
fontSize: 24,
color: 'black',
},
image: {
alignSelf: 'center',
height: hp(40),
width: hp(40),
marginTop: hp(3),
},
itemStyle: {
backgroundColor: 'pink',
alignItems: 'center',
justifyContent: 'center',
height: 150,
flex: 1,
margin:1,
width: WIDTH / numColums
},
itemText: {
fontSize: 50
}
});
I have attached an image of what it looks like now:
Here
UPDATE
I have updated the datalist to this:
const dataList = [{ key: '1',image: required('../assets/backGround.png')}, { key: '2',image: required('../assets/backGround.png') }, { key: '3' ,image: required('../assets/backGround.png')}]
And the view to this:
<View style={itemStyle}>
{/* <Text style={styles.itemText}>{item.key}</Text> */}
<Image
style={styles.image}
source={item.image}
/>
</View>
and I now get the error:
TypeError: (0, _reactNative.required) is not a function. (In '(0, _reactNative.required)('../assets/backGround.png')', '(0, _reactNative.required)' is undefined)
const dataList = [{ key: '1',image: required('../assets/backGround.png')}, { key: '2',image: required('../assets/backGround.png') }, { key: '3' ,image: required('../assets/backGround.png')}]
needs to be
const dataList = [{ key: '1',image: require('../assets/backGround.png')}, { key: '2',image: require('../assets/backGround.png') }, { key: '3' ,image: require('../assets/backGround.png')}]
you need to add require() to the source in the image tag
like my title said I struggle with this though below is a example
{ id: '1', name: 'one' },
{ id: '2', name: 'two' },
{ id: '3', name: 'three' },
{ id: '4', name: 'four' },
this is a flatlist after I remove item with id '2' I want id 3 become 2 and id 4 become 3 so the flatlist after id 2 be removed will like
{ id: '1', name: 'one' },
{ id: '2', name: 'three' },
{ id: '3', name: 'four' },
here is my code
export default function Listdata({ route }) {
const [itemData, newItem] = React.useState([]);
const [itemState, setItemState] = React.useState(itemData);
const [idmoi, incr,] = React.useState(1);
const [textNhapVao, setTextNhapVao] = React.useState('');
const tinhToanId = (t) => {
var idNew = [itemData.id];
incr(idNew - 1);
}
const themItem = () => {
var arrayMoi = [...itemData, { id: idmoi, name: textNhapVao }];
incr(idmoi + 1)
console.log('idddd')
console.log(idmoi)
setItemState(arrayMoi);
newItem(arrayMoi);
}
<View>
</View>
const keyboardVerticalOffset = Platform.OS === 'ios' ? 40 : 0
const xoaItem = (IItem) => {
console.log('routeeee')
console.log(route.params.paramKey)
setItemState(prevItemState => prevItemState.filter((_item, _Index) => _Index !== IItem));
}
return (
<Container style={styles.container}>
<View style={{
alignItems: 'center',
justifyContent: 'center',
borderBottomWidth: 1,
borderColor: '#d7d7d7',
}}>
<Text style={{ fontWeight: 'bold', fontSize: 30, color: 'green' }}>Xin Chào {route.params.paramKey}</Text>
</View>
<FlatList
data={itemState}
keyExtractor={(item, index) => index}
renderItem={({ item, index }) => (
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
<View style={{ marginLeft: 20 }}>
<Text style={{ fontSize: 30, color: 'red' }} >{item.id}{'\n'}{item.name}</Text>
</View>
<View style={{ justifyContent: 'center', marginRight: 20 }}>
<TouchableOpacity
style={{
width: '100%',
backgroundColor: 'red',
}}
activeOpacity={0.7}
onPress={() => xoaItem(index)}
>
<IconFE name='trash-2' size={30} style={{ color: 'orange' }} />
</TouchableOpacity>
</View>
</View>
)}
/>
<View
style={{
position: 'relative', height: 50,
borderTopWidth: 1,
borderColor: '#d7d7d7',
}}>
<KeyboardAvoidingView enabled behavior={Platform.OS === "ios" ? "padding" : null} keyboardVerticalOffset={keyboardVerticalOffset} >
<View
style={{
alignItems: 'center', position: 'relative',
flexDirection: 'row',
justifyContent: 'space-between',
marginLeft: 20,
marginRight: 20,
}}>
<Input
onChangeText={data => setTextNhapVao(data)}
placeholder='Nhập Vào Đây'></Input>
<TouchableOpacity
title="Thêm"
onPress={themItem}>
<IconFE name='check-square' size={30} style={{ color: 'blue' }} />
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
</View>
</Container>
)
}
and below is my screenshot flatlist: https://uphinh.org/image/9OLoCN
You could take a function which removes the object at the given index.
The function takes the removed array, takes the object at start and gets the id then it loops from the index until the end and updates all id properties.
const
remove = (array, index) => {
let removed = array.splice(index, 1);
if (!removed.length) return array;
let id = +removed[0].id;
while (index < array.length) array[index++].id = (id++).toString();
return array;
},
data = [{ id: '1', name: 'one' }, { id: '2', name: 'two' }, { id: '3', name: 'three' }, { id: '4', name: 'four' }];
remove(data, 1);
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
From the provided array remove the selected array by splice method by finding its index
Working example: https://snack.expo.io/#msbot01/137768
import React, { Component } from 'react';
import {View, Text, StyleSheet, Image, TouchableOpacity, Dimensions, FlatList} from 'react-native';
export default class SupervisorDashboard extends Component<Props> {
constructor(props) {
super(props);
this.state = {
userData:[
{id:1, name:"One"},
{id:2, name:"Two"},
{id:3, name:"Three"},
{id:4, name:"Four"},
{id:5, name:"Five"},
{id:6, name:"Six"},
]
}
}
componentDidMount(){
}
removeItem(index){
this.state.userData.splice(index, 1);
var array = []
// console.log(JSON.stringify(this.state.userData))
for(var i=0; i< this.state.userData.length; i++){
var eachElement = {id: (i+1), name: this.state.userData[i].name }
array.push(eachElement)
}
console.log(JSON.stringify(array))
this.setState({})
}
renderItem(item, index){
// console.log(item.id)
return(
<View style={{height:60, width:'90%', marginTop:10, marginLeft:'5%', marginRight:'5%', flexDirection:'row', justifyContent:'space-between', alignItems:'center', borderRadius:10, borderWidth:1, borderColor:'#ececec', padding:10}}>
<Text>{item.id}</Text>
<Text>{item.name}</Text>
<TouchableOpacity onPress={()=>{this.removeItem(index)}} style={{marginRight:10, backgroundColor:'grey', height:'100%', justifyContent:"center", borderRadius:10, padding:10}}>
<Text>Click to remove</Text>
</TouchableOpacity>
</View>
)
}
render(){
return(
<View style={{flex:1, backgroundColor:'white'}}>
<FlatList
data={this.state.userData}
renderItem={({ item, index })=>this.renderItem(item, index)}
keyExtractor={item => item.id}
/>
</View>
);
}
}
const styles = StyleSheet.create({
background: {
backgroundColor: 'red'
}
});
As far as I understand your id is not continues (1,2,3...), because if so, you don't need to mutate id at all, you can just use array indices instead. Anyway, if you assume that id is not continues, we can try following algorithm:
Find remove index,
Map element n to n+1 for indices higher than remove index,
Remove last element (it will be our final remove item, that has been pushed to the end).
Code example:
const data = [
{ id: '1', name: 'one' },
{ id: '2', name: 'two' },
{ id: '5', name: 'five' },
{ id: '6', name: 'six' }]
const removeFromArr = (arr, name) => {
const removeIdx = arr.findIndex(e => e.name === name)
return arr.map((e, i, a) => removeIdx <= i ? ({...e, name: a?.[i + 1]?.name}) : e) // map element n to n+1 if higher than remove idx
.slice(0, arr.length - 1) // remove last item
}
const newData = removeFromArr(data, "two")
console.log(newData)
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can easily achieve this result
Find the index of the element that you want to remove using findIndex
Then divide the array into two halves
Add one to the second array after it is parsed to int.
join the array.
Be sure to cover the corner case if the element is not in arr.
const arr = [
{ id: "1", name: "one" },
{ id: "2", name: "two" },
{ id: "3", name: "three" },
{ id: "4", name: "four" },
];
function resetIds(arr) {
return arr.map((o) => {
return { ...o, id: `${parseInt(o.id) - 1}` };
});
}
const id = "2";
const elementToRemoveIndex = arr.findIndex((o) => o.id === id);
const result =
elementToRemoveIndex !== -1
? [
...arr.slice(0, elementToRemoveIndex),
...resetIds(arr.slice(elementToRemoveIndex + 1)),
]
: [...arr];
console.log(result);
My Flatlist does not work for me, Some one please review and give me a solution
const data = [
'hai', 'hloooo'
]
class HotelList extends Component {
render() {
console.log('data==========', data)
return (
<View style = {{flex: 1, height: '100%', width: '100%'}}>
<Text>Hai</Text>
<FlatList
data = {data}
keyExtractor = {(item, index) => index.toString()}
renderItem = {itemData => {
console.log(itemData)
return (
<View style = {{width: '100%', height: 100, flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: 'yellow'}}>
<Text>Holaaaaaa</Text>
</View>
)
}}
/>
</View>
)
}
}
export default HotelList
Basically you have missed some basic theory about how to use a flat list in react native. See official documentation here
Solution :
You need to add id to your array in order to make keyExtractor work
const data = [
{
id: "1",
title: "First Item",
},
{
id: "2",
title: "Second Item",
},
{
id: "3",
title: "Third Item",
},
];
class HotelList extends Component {
render() {
console.log("data==========", data);
return (
<View style={{ flex: 1, height: "100%", width: "100%" }}>
<Text>Hai</Text>
<FlatList
data={data}
keyExtractor={(item) => item.id}
renderItem={(item) => {
console.log(item);
return (
<View
style={{
width: "100%",
height: 100,
flex: 1,
alignItems: "center",
justifyContent: "center",
backgroundColor: "yellow",
}}
>
<Text>{item.title}</Text>
</View>
);
}}
/>
</View>
);
}
}
export default HotelList;
Not sure where I go about declaring the array with which I want to search from, any assistance would be appreciated. I believe my issue is that I am declaring the "services' array in the incorrect area but I am not sure where else to put it! Or if the commas are the right character to be using in between strings/services
import React, { useState, Component } from 'react';
import { StyleSheet, StatusBar, View, Text, Button, TouchableOpacity } from 'react-native';
import AutoComplete from 'react-native-autocomplete-input';
class CareProviderSequenceScreen extends Component {
constructor (props) {
super (props);
this.state = {
services: [],
query: '',
}
}
render() {
const query = this.state;
const services = {
"Pick up my Prescription",
'Pick up groceries',
'Pick up dry cleaning',
'Pick up my pet',
}
return (
<View style={styles.container}>
<Autocomplete
autoCapitalize="none"
autoCorrect={false}
containerStyle={styles.autocompleteContainer}
//data to show in suggestion
data={services.length === 1 && comp(query, services[0].title) ? [] : services}
//default value if you want to set something in input
defaultValue={query}
/*onchange of the text changing the state of the query which will trigger
the findFilm method to show the suggestions*/
onChangeText={text => this.setState({ query: text })}
placeholder="Enter your need"
renderItem={({ item }) => (
//you can change the view you want to show in suggestion from here
<TouchableOpacity onPress={() => this.setState({ query: item.title })}>
<Text style={styles.itemText}>
{item.title} ({item.release_date})
</Text>
</TouchableOpacity>
)}
/>
<View style={styles.descriptionContainer}>
{services.length > 0 ? (
<Text style={styles.infoText}>{this.state.query}</Text>
) : (
<Text style={styles.infoText}>Enter The Film Title</Text>
)}
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#F5FCFF',
flex: 1,
padding: 16,
marginTop: 40,
},
autocompleteContainer: {
backgroundColor: '#ffffff',
borderWidth: 0,
},
descriptionContainer: {
flex: 1,
justifyContent: 'center',
},
itemText: {
fontSize: 15,
paddingTop: 5,
paddingBottom: 5,
margin: 2,
},
infoText: {
textAlign: 'center',
fontSize: 16,
},
});
export default CareProviderSequenceScreen ;
CareProviderSequenceScreen .navigationOptions = () => ({
title: "Home & Personal Care",
headerTintColor: '#9EBBD7',
headerStyle: {
height: 65,
backgroundColor: '#1E5797',
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.20,
shadowRadius: 1.41,
elevation: 2,}
});
First, you are assigning an object to services array.
Second, you are not accessing the query state properly. It should be
const { query } = this.state