I am using camera roll for react native to get the images on my mobile device, I used first: 1, after the camera roll function runs it stores the end_cursor from the data and uses the it in the subsequent camera roll requests as the after variable, i.e
CameraRoll.getPhotos({
first: 1,
assetType: 'Photos',
after: end_cursor
})
I then run a function when the end of the flatlist is gotten too, to load more images based on the end_cursor variable.
The images keep coming twice, there are duplicate images in the state i.e [image 1,image 1, image 2, image 2, ....], what may be causing this error, This is my full code below
constructor(props) {
super(props);
this.state = {
photos: [],
lastCursor: null,
noMorePhotos: false,
loadingMore: false,
};
}
tryPhotoLoad() {
if (!this.state.loadingMore) {
this.setState({ loadingMore: true }, () => { this.loadPhotos(); });
}
}
loadPhotos() {
const fetchParams = {
first: 1,
assetType: 'Photos',
};
if (this.state.lastCursor) {
// console.log("last cursor "+this.state.lastCursor)
fetchParams.after = this.state.lastCursor;
}
CameraRoll.getPhotos(fetchParams).then((data) => {
this.appendAssets(data);
}).catch((e) => {
// console.log(JSON.stringify(e));
});
}
appendAssets(data) {
console.log("\n"+"\n"+"\n"+JSON.stringify(data)+"\n"+"\n"+"\n")
const assets = data.edges;
const nextState = {
loadingMore: false,
};
if (!data.page_info.has_next_page) {
nextState.noMorePhotos = true;
}
if (assets.length > 0) {
this.setState({lastCursor: data.page_info.end_cursor})
// nextState.lastCursor = data.page_info.end_cursor;
let len = assets.length;
// console.log(len);
for (let i = 0; i < len; i++) {
let row = assets[i];
// console.log(row);
this.setState(prevState => ({
photos: [...prevState.photos, row]
}));
}
}
// console.log("\n"+"\n"+"\n"+JSON.stringify(nextState)+"\n"+"\n"+"\n");
this.setState(nextState);
}
endReached() {
if (!this.state.noMorePhotos) {
this.tryPhotoLoad();
}
}
componentDidMount(){
this.tryPhotoLoad();
}
render() {
const images =(
<FlatList
data={this.state.photos}
numColumns={4}
renderItem={({ item, index }) => (
<View style={{width: '25%',
height: height}}>
<Image
key={index}
resizeMode={'cover'}
style={{
flex: 1
}}
source={{ uri: item.node.image.uri }}
/></View>
)}
keyExtractor={(item, index) => `list-item-${index}`}
onEndReached={this.endReached()}
onEndReachedThreshold={0}
/>
);
return (
<View
style={{ flex: 1, backgroundColor: "#DDDBC7", flexDirection: "column" }}
>
<ScrollView>
{images}
</ScrollView>
);
}
Related
It might sound silly but I am just learning here
I am trying to convert a component to a function-based component. I did everything right but I am stuck on something very silly
I have this code for Discover
export default class Discover extends React.PureComponent {
state = {
items: [],
};
cellRefs: {};
constructor(props) {
super(props);
this.cellRefs = {};
}
what is the correct way to convert cellRefs to work with the function I have? I tried everything when I do this in my class file it is fine it gives me an object with the things I need.
const cell = this.cellRefs[item.key];
However,
const cell = cellRefs[item.key];
is just giving undefined
Full code for the converted component
import React, { useState, useEffect, useRef, Children } from 'react';
import {
StyleSheet,
Text,
View,
FlatList,
Dimensions,
TouchableOpacity,
Image,
} from 'react-native';
import { Video } from 'expo-av';
const { height, width } = Dimensions.get('window');
const cellHeight = height * 0.6;
const cellWidth = width;
const viewabilityConfig = {
itemVisiblePercentThreshold: 80,
};
class Item extends React.PureComponent {
video: any;
componentWillUnmount() {
if (this.video) {
this.video.unloadAsync();
}
}
async play() {
const status = await this.video.getStatusAsync();
if (status.isPlaying) {
return;
}
return this.video.playAsync();
}
pause() {
if (this.video) {
this.video.pauseAsync();
}
}
render() {
const { id, poster, url } = this.props;
const uri = url + '?bust=' + id;
return (
<View style={styles.cell}>
<Image
source={{
uri: poster,
cache: 'force-cache',
}}
style={[styles.full, styles.poster]}
/>
<Video
ref={ref => {
this.video = ref;
}}
source={{ uri }}
shouldPlay={false}
isMuted
isLooping
resizeMode="cover"
style={styles.full}
/>
<View style={styles.overlay}>
<Text style={styles.overlayText}>Item no. {id}</Text>
<Text style={styles.overlayText}>Overlay text here</Text>
</View>
</View>
);
}
}
interface FeedListProps {
}
export const FeedList: React.FC<FeedListProps> = (props) => {
const initialItems = [
{
id: 1,
url: 'https://s3.eu-west-2.amazonaws.com/jensun-uploads/shout/IMG_1110.m4v',
poster:
'https://s3.eu-west-2.amazonaws.com/jensun-uploads/shout/norwaysailing.jpg',
},
{
id: 2,
url:
'https://s3.eu-west-2.amazonaws.com/jensun-uploads/shout/croatia10s.mp4',
poster:
'https://s3.eu-west-2.amazonaws.com/jensun-uploads/shout/croatia10s.jpg',
},
];
const [items, setItems] = useState([]);
//this.cellRefs = {};
//let cellRefs: {};
//cellRefs= {};
const cellRefs = React.useRef({})
const viewConfigRef = React.useRef({ itemVisiblePercentThreshold: 80 })
useEffect(() => {
loadItems();
setTimeout(loadItems, 1000);
setTimeout(loadItems, 1100);
setTimeout(loadItems, 1200);
setTimeout(loadItems, 1300);
}, []);
const _onViewableItemsChanged = React.useRef((props)=>{
const changed = props.changed;
changed.forEach(item => {
const cell = cellRefs[item.key];
console.log("CALLING IF"+ cell + " " + item.key)
if (cell) {
if (item.isViewable) {
console.log("PLAY OS CALLED")
cell.play();
} else {
console.log("Pause is played")
cell.pause();
}
}
});
});
function loadItems(){
const start = items.length;
const newItems = initialItems.map((item, i) => ({
...item,
id: start + i,
}));
const Litems = [...items, ...newItems];
setItems( Litems );
};
function _renderItem({ item }){
return (
<Item
ref={cellRefs[item.id]}
{...item}
/>
);
};
return (
<View style={styles.container}>
<FlatList
style={{ flex: 1 }}
data={items}
renderItem={_renderItem}
keyExtractor={item => item.id.toString()}
onViewableItemsChanged={_onViewableItemsChanged.current}
initialNumToRender={3}
maxToRenderPerBatch={3}
windowSize={5}
getItemLayout={(_data, index) => ({
length: cellHeight,
offset: cellHeight * index,
index,
})}
viewabilityConfig={viewabilityConfig}
removeClippedSubviews={true}
ListFooterComponent={
<TouchableOpacity onPress={loadItems}>
<Text style={{ padding: 30 }}>Load more</Text>
</TouchableOpacity>
}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
cell: {
width: cellWidth - 20,
height: cellHeight - 20,
backgroundColor: '#eee',
borderRadius: 20,
overflow: 'hidden',
margin: 10,
},
overlay: {
position: 'absolute',
top: 0,
right: 0,
bottom: 0,
left: 0,
backgroundColor: 'rgba(0,0,0,0.4)',
padding: 40,
},
full: {
position: 'absolute',
top: 0,
right: 0,
bottom: 0,
left: 0,
},
poster: {
resizeMode: 'cover',
},
overlayText: {
color: '#fff',
},
});
Should be enough to use a functional component and use useRef([]) initialized as an array
Working example:
https://snack.expo.io/2_xrzF!LZ
It would be best if you could inline your source code into stack overflow, than keeping it in a separate link. However I took a look at the component, and I think the issue is with how you are using props.
On line 91,
export const FeedList: React.FC<FeedListProps> = ({}) => {
So here, you need to get the props as an argument. Earlier with the class component it was available at this.props. However here you need to pass it as below,
export const FeedList: React.FC<FeedListProps> = (props) => {
Or you may destructure the props as below,
export const FeedList: React.FC<FeedListProps> = ({changed}) => {
You will also need to modify the interface on line 87 to reflect the type.
My goal is to animate the screen to each MapView.Marker when swipping to each Card (Animated.ScrollView) . Already tried this and it worked but now I did some changes to my codes because I added React Redux.
I think might be the problem is about the pointing out the React Redux State or the Key, because I get warning about Key. It says:
Warning: Each child in a list should have unique "key" prop.
I want to animate the screen to each MapView.Marker like this:
Here are my codes:
componentWillMount() {
this.index = 0;
this.animation = new Animated.Value(0);
}
componentDidMount() {
// We should detect when scrolling has stopped then animate
// We should just debounce the event listener here
this.animation.addListener(({ value }) => {
let index = Math.floor(value / CARD_WIDTH + 0.3); // animate 30% away from landing on the next item
if (index >= this.props.events.length) {
index = this.props.events.length - 1;
} else {
return null;
}
if (index <= 0) {
index = 0;
} else {
return null;
}
clearTimeout(this.regionTimeout);
this.regionTimeout = setTimeout(() => {
if (this.index !== index) {
this.index = index;
const { focusedLocation } = this.props.events.location.value.latitude && this.props.events.location.value.longitude[index];
this.map.animateToRegion(
{
...focusedLocation,
latitudeDelta: this.state.focusedLocation.latitudeDelta,
longitudeDelta: this.state.focusedLocation.longitudeDelta,
},
350
);
}
}, 10);
});
}
render() {
//For the Scroll View Card
const interpolations = this.props.events.map((marker, index) => {
const inputRange = [
(index - 1) * CARD_WIDTH,
index * CARD_WIDTH,
((index + 1) * CARD_WIDTH),
];
const scale = this.animation.interpolate({
inputRange,
outputRange: [1, 2.5, 1],
extrapolate: "clamp",
});
const opacity = this.animation.interpolate({
inputRange,
outputRange: [0.35, 1, 0.35],
extrapolate: "clamp",
});
return { scale, opacity };
});
return(
<View style={styles.container}>
{/* <StatusBar backgroundColor={'transparent'} translucent={true}/> */}
<MapView
style={styles.container}
initialRegion={this.state.focusedLocation}
onPress={this.pickLocationHandler}
showsUserLocation={true}
ref={ref => this.map = ref} //For animating map movement
>
{userMarker}
{this.props.events.map((marker, index) => {
if(marker.location) {
const scaleStyle = {
transform: [
{
scale: interpolations[index].scale,
},
],
};
const opacityStyle = {
opacity: interpolations[index].opacity,
};
return (
<MapView.Marker key={index} coordinate={marker.location}>
<Animated.View style={[styles.markerWrap, opacityStyle]}>
<Animated.View style={[styles.ring, scaleStyle]} />
<View style={styles.marker} />
</Animated.View>
</MapView.Marker>
);
} else {
return null;
}
})}
</MapView>
<Animated.ScrollView
horizontal
scrollEventThrottle={1}
pagingEnabled={true}
showsHorizontalScrollIndicator={false}
snapToInterval={snapInterval}
onScroll={Animated.event(
[
{
nativeEvent: {
contentOffset: {
x: this.animation,
},
},
},
],
{ useNativeDriver: true }
)}
style={styles.scrollView}
contentContainerStyle={styles.endPadding}
>
<FlatList
keyExtractor={this._keyExtractor}
horizontal
data={this.props.events}
renderItem={(info) => (
<TouchableOpacity onPress={() => this.itemSelectedHandler(info.item.key)}>
<View style={styles.card} key={info.item.key}>
<Image
source={info.item.image}
style={styles.cardImage}
resizeMode="cover"
/>
<View style={styles.textContent}>
<Text numberOfLines={1} style={styles.cardtitle}>{info.item.name}</Text>
<Text numberOfLines={1} style={styles.cardDescription}>
{info.item.description}
</Text>
</View>
</View>
</TouchableOpacity>
)}
/>
</Animated.ScrollView>
<TouchableOpacity onPress={this.getLocationHandler} style={styles.iconContainer}>
<Icon name="md-locate" size={30} color="blue"/>
</TouchableOpacity>
</View>
);
}
}
const mapStateToProps = state => {
return {
events: state.events.events
};
};
export default connect(mapStateToProps)(EventMap);
My codes for React Redux:
../../reducers/events.js:
const reducer = (state = initialState, action) => {
switch (action.type) {
case ADD_EVENT:
return {
...state,
events: state.events.concat({
key: `${Math.random()}`,
name: action.eventName,
description: action.eventDescription,
location: action.location,
image: {
uri: "https://c1.staticflickr.com/5/4096/4744241983_34023bf303_b.jpg"
}
})
};
// Here in my code am calling 2 APIS 1.( createViewGroup = async () =>)one for get data from server and set on FlatList , id,sensorType inventory,
2 second api ("SensorDelt = (rowIndex) => ") am calling for delete particular list iteam from server ,I mean after touching particular list item , i am taking id no and that id ({"password":"admin","username":"admin","sensorid":"here i have to send id no"})am sending to server and that id will be delete .
In my code am using Swipeout delete button to delete list item ,but it is working locally, not deleting from server .
Please help
import * as React from "react";
import {
View,
Text,
TextInput,
FooterTab,
Button,
TouchableOpacity,
ScrollView,
StyleSheet,
ActivityIndicator,
Header,
Alert,
AsyncStorage,
FlatList
} from "react-native";
import { Table, Row, Rows } from "react-native-table-component";
import { createStackNavigator, createAppContainer } from "react-navigation";
import { SearchBar } from "react-native-elements";
// You can import from local files
//import AssetExample from './components/AssetExample';
// or any pure javascript modules available in npm
import { Card } from "react-native-paper";
import Swipeout from "react-native-swipeout";
class OpenApplianceIssue extends React.Component {
constructor() {
super();
this.state = {
AbcSdata: null,
loading: true,
search: "",
tableData: [],
qrData: "",
selectedPriority: "",
selectedIssue: "",
selectedReason: "",
selectedTriedRestart: "",
selectedPowerLED: "",
selectedBurning: "",
selectedNoise: "",
rowID: "",
activeRow: null
};
this.setDate = this.setDate.bind(this);
}
swipeBtns = [
{
text: "Delete",
type: "delete",
backgroundColor: "red",
underlayColor: "rgba(0, 0, 0, 1, 0.6)",
onPress: () => {
console.log("Deleting Row with Id ", this.state.activeRow);
{
this.deleteNote(this.state.activeRow);
this.onClickListener("del");
}
}
//onPress:() => this.onClickListener('tag')}
}
];
removeItem = (items, i) =>
items.slice(0, i).concat(items.slice(i + 1, items.length));
deleteNote = rowIndex => {
//add your custome logic to delete the array element with index.
// this will temporary delete from the state.
let filteredData = this.removeItem(this.state.AbcSdata, rowIndex);
this.setState({ AbcSdata: [] }, () => {
this.setState({ AbcSdata: filteredData }, () => {
console.log("Row deleted.", rowIndex);
});
});
};
setDate(newDate) {}
_loadInitialState = async () => {
const { navigation } = this.props;
const qdata = navigation.getParam("data", "NA").split(",");
var len = qdata.length;
const tData = [];
console.log(len);
for (let i = 0; i < len; i++) {
var data = qdata[i].split(":");
const entry = [];
entry.push(`${data[0]}`);
entry.push(`${data[1]}`);
tData.push(entry);
}
this.setState({ tableData: tData });
console.log(this.state.tableData);
this.setState({ loading: true });
};
// Delete Sensors ********************
SensorDelt = rowIndex => {
//const Sensorid_Data = this.props.navigation.state.params.item.id;
let filteredData = this.removeItem(this.state.AbcSdata, rowIndex);
let ABHI = filteredData//const Sensorid_Data = this.state.rowIndex;
.console
.log("Value Abhi" + filteredData);
Alert.alert("Value" + filteredData);
fetch("http:/Dsenze/userapi/sensor/delsensor", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
password: "admin",
username: "admin",
sensorid: filteredData
})
})
.then(response => {
//console.log(response);
return response.json();
})
.then(res => {
if (res.success == "true") {
Alert.alert("Sensor Added");
this.props.navigation.replace("OpenApplianceIssue");
} else {
Alert.alert("Success false");
}
});
};
handleValueChange(SensortypeId) {
this.setState({ SensortypeId });
}
// Delete sensors ***********************
onClickListener = viewId => {
if (viewId == "tag") {
this.props.navigation.navigate("AddSensors");
} else if (viewId == "del") {
//this.props.navigation.navigate('AddSensors');
this.SensorDelt();
}
};
componentDidMount() {
//this._loadInitialState().done();
this.createViewGroup();
}
// Get Sensor list ********************************************
createViewGroup = async () => {
try {
const response = await fetch(
"http://Dsenze/userapi/sensor/viewsensor",
{
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
password: "admin",
username: "admin",
startlimit: "0",
valuelimit: "10"
})
}
);
const responseJson = await response.json();
const { sensorData } = responseJson;
this.setState({
AbcSdata: sensorData,
loading: false
});
} catch (e) {
console.error(e);
}
};
clickedItemText(OpenApplianceIssue) {
this.props.navigation.navigate("Item007", { item: OpenApplianceIssue });
//Abc = this.props.navigation.state.params.item.id;
}
updateSearch = search => {
this.setState({ search });
};
keyExtractor = ({ id }) => id.toString();
keyExtractor = ({ inventory }) => inventory.toString();
onSwipeOpen(rowId, direction) {
if (typeof direction !== "undefined") {
this.setState({ activeRow: rowId });
console.log("Active Row", rowId);
}
}
renderItem = ({ item, index }) => (
<Swipeout
style={styles.SwipeBG}
right={this.swipeBtns}
close={this.state.activeRow !== index}
rowID={index}
sectionId={1}
autoClose={true}
// onOpen = {(secId, rowId, direction) => this.onSwipeOpen(rowId, direction)}
>
<TouchableOpacity
style={styles.item}
activeOpacity={0.4}
onPress={() => {
this.clickedItemText(item);
}}
>
{/* //onPress={this.viewNote(item)} >
> */}
<Text>Id : {item.id}</Text>
<Text>Inventory : {item.inventory}</Text>
<Text>SensorType : {item.sensorType}</Text>
<Text>TypeName : {item.typeName}</Text>
</TouchableOpacity>
</Swipeout>
);
// viewNote =(item) => {
// this.props.navigator.push({
// title: 'The Note',
// component: this.ViewNote,
// passProps: {
// noteText: item,
// noteId: this.noteId(item),
// }
// });
// console.log("View Note Success");
// }
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: "86%",
backgroundColor: "#CED0CE"
}}
/>
);
};
render() {
const { loading, AbcSdata } = this.state;
const state = this.state;
return (
<ScrollView>
<View style={styles.container1}>
<Button
full
rounded
style={{ fontSize: 20, color: "green" }}
styleDisabled={{ color: "red" }}
onPress={() => this.onClickListener("tag")}
title="Add Sensors"
>
Add Sensors
</Button>
</View>
<View style={styles.container1}>
{this.state.loading ? (
<ActivityIndicator size="large" />
) : (
<FlatList
style={styles.ListDATA}
data={AbcSdata}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
extraData={this.state.activeRow}
ItemSeparatorComponent={this.renderSeparator}
/>
)}
</View>
<View>
<Text
style={{ alignSelf: "center", fontWeight: "bold", color: "black" }}
>
Inventory Details
</Text>
<Table
borderStyle={{
borderWidth: 2,
borderColor: "#c8e1ff",
padding: 10,
paddingBottom: 10
}}
>
<Rows data={state.tableData} textStyle={styles.text} />
</Table>
</View>
</ScrollView>
);
}
}
export default (OpenApplianceIssue = createStackNavigator({
Item007: { screen: OpenApplianceIssue }
}));
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
backgroundColor: "#ecf0f1",
padding: 8
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: "bold",
textAlign: "center"
},
SwipeBG: {
backgroundColor: "#ffffff",
marginLeft: 7,
marginTop: 3
},
ListDATA: {
backgroundColor: "#ffffff",
marginLeft: 5,
marginTop: 3
}
});
Thanks
I just want to capture image using camera API
Then Store it in array
then view one by one image horizontally in React native
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
TouchableOpacity,
Image,
PixelRatio
} from 'react-native';
import ImagePicker from 'react-native-image-picker';
let ret;
export default class Location extends Component {
constructor(props){
super(props);
this.state = {
latitude: null,
longitude: null,
address: 'address',
MyAddress: null,
error: null,
};
}
state = {
avatarSource: null,
videoSource: null
};
selectPhotoTapped() {
const options = {
quality: 1.0,
maxWidth: 500,
maxHeight: 500,
storageOptions: {
skipBackup: true
}
};
To get Image, I used this.
ImagePicker.showImagePicker(options, (response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled photo picker');
}
else if (response.error) {
console.log('ImagePicker Error: ', response.error);
}
else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
}
else {
let source = { uri: response.uri };
// You can also display the image using data:
//let source = { uri: 'data:image/jpeg;base64,' + response.data };
this.setState({
avatarSource: source
});
}
});
}
Then how to process to view list of image like adpater.
return (
<View style={{ flexGrow: 1, alignItems: 'center', justifyContent: 'center' }}>
To show the image in one view ,i have done this. i want to view multiple image like view pager.Like [] [] [] []
<TouchableOpacity onPress={this.selectPhotoTapped.bind(this)}>
<View style={[styles.avatar, styles.avatarContainer, {marginBottom: 20}]}>
{ this.state.avatarSource === null ? <Text>Select a Photo</Text> :
<Image style={styles.avatar} source={this.state.avatarSource} />
}
</View>
</TouchableOpacity>
</View>
)
}
}
After few hours i have done this
First save image uri in array then show in list..
let dataStorage = [{uri: response.uri}, ...this.state.dataStorage]
this.setState({dataStorage})
<FlatList
horizontal
data={this.state.dataStorage}
renderItem={({ item: rowData }) => {
return (
<View style={[styles.avatar, styles.avatarContainer, {marginBottom: 20}]}>
{ <Image style={styles.avatar} source={{uri:rowData.uri}} /> }
</View>
);
}
}
keyExtractor={(item, index) => index}
/>
Using Expo's ImagePicker this can be achieved.
Below is my code that might help you.
Note: Its performance is slow but it works.
1) state:
constructor(props) {
super(props);
this.state = {
images: []
};
}
2) openCamera function:
openCamera = async () => {
const { status } = await Permissions.askAsync(
Permissions.CAMERA,
Permissions.CAMERA_ROLL
);
this.setState({
hasCameraPermission: status === 'granted',
hasGalleryPermission: status === 'granted'
});
if (this.state.hasCameraPermission && this.state.hasGalleryPermission) {
ImagePicker.launchCameraAsync({
aspect: [1, 1],
quality: 0.2,
base64: true
})
.then(async result => {
if (!result.cancelled) {
await this.setState({
images: this.state.images.concat(result.uri)
});
Alert.alert(
'Add another picture? ',
null,
[
{
text: 'Yes',
onPress: () => this.openCamera()
},
{ text: 'No' }
],
{ cancelable: false }
);
}
console.log(this.state.images);
})
.catch(error => console.log(error));
}
};
3) To display Image:
showImages = () => {
let temp_image = [];
this.state.images.map((item, index) => {
let tempKey = item + '123';
temp_image.push(
<View key={tempKey}>
<View
key={index}
style={{
height: 100,
width: 100,
borderColor: '#dddddd'
}}
>
<Image
key={index}
source={{ uri: item }}
style={{
flex: 1,
flexDirection: 'row',
backgroundColor: 'silver',
padding: 5,
borderRadius: 5,
height: null,
width: null,
margin: 3,
resizeMode: 'cover'
}}
/>
</View>
<View key={index + 1}>
<TouchableOpacity
key={index + 2}
style={{
flex: 1,
justifyContent: 'center',
alignSelf: 'center',
width: '100%'
}}
onPress={() => {
this.removeImage(index);
this.forceUpdate();
}}
>
<Text
key={index + 3}
style={{
alignSelf: 'center',
color: '#CE3C3E',
fontWeight: 'bold'
}}
>
Delete
</Text>
</TouchableOpacity>
</View>
</View>
);
});
console.log('state images: ', this.state.images);
return temp_image;
};
4) To delete image:
removeImage = index => {
Alert.alert('Delete this image?', null, [
{
text: 'Yes',
onPress: () => {
this.state.images.splice(index, 1);
// console.log(this.state.images);
this.forceUpdate();
}
},
{ text: 'No' }
]);
};
5) And in render() function:
<ScrollView horizontal={true} style={{ flex: 1, flexDirection: 'row' }} >
{this.showImages()}
</ScrollView>
I have two functions that are not rendering: renderTeachers() and renderSubjects(). They render based on the length of the teachers array in the state object. I console logged state.teachers and the result is as expected, the array length is more than one, but the functions still don't render. I don't understand why these functions are not rendering.
class Search extends Component {
state = {
teachers: [],
subjects: [],
rating: 3.5,
};
requestData = (queryObj) => {
console.log(queryObj);
const client = algoliasearch('__ID__', '__KEY__');
const queries = [{
indexName: 'teachers',
query: queryObj,
filters: 'Rating >= 3.5',
}, {
indexName: 'subjects',
query: queryObj,
}];
if (queryObj === '') {
this.setState({ showSearchVal: false });
} else {
client.search(queries, this.searchCallback.bind(this));
}
}
searchCallback = (err, content) => {
if (err) {
console.error(err);
return;
}
this.setState({ teachers: content.results[0].hits, subjects: content.results[1].hits });
}
renderSubjects = () => {
if (this.state.subjects.length >= 1) {
return this.state.subjects.map(subject => <SubjectDetail key={subject.objectID} subject={subject} />);
}
return null;
}
renderTeachers = () => {
console.log('in');
if (this.state.teachers.length >= 1) {
return this.state.teachers.map(teacher => <SearchDetail key={teacher.UID} person={teacher} />);
}
return null;
}
render() {
return (
<View>
<Header search onPress={() => this.searchBar.show()} />
<SearchBar
backgroundColor='#02254e'
iconColor='#4f5d6d'
placeholderTextColor='#4f5d6d'
backButton={<Icon name='keyboard-backspace' size={24} color='#4f5d6d' style={{ alignSelf: 'center' }} />}
textColor='white'
animate={false}
handleChangeText={this.requestData}
selectionColor='#01152d'
fontFamily='avenir_heavy'
backCloseSize={24}
ref={(ref) => { this.searchBar = ref; }}
/>
<View style={{ width, height, alignItems: 'center', flex: 1 }}>
<ScrollView style={{ flex: 1 }}>
<Text style={styles.topResultTextStyle}>
{this.state.subjects.length >= 1 ? 'Subjects' : ''}
</Text>
{this.renderSubjects()}
<Text style={styles.topResultTextStyle}>
{this.state.teachers.length >= 1 ? 'Teachers' : ''}
</Text>
{this.renderTeachers()}
</ScrollView>
</View>
</View>
);
}
}
export { Search };
from the code you post, I can't see a reason why teachers / subjects won't render. My question is, how do you set the teachers /subjects arrays ? without changing state / props, react component shouldn't render. Can you please share the arrays set code ?