Image is overflowing outside the size of FlatList single grid - image

I am currently working on making a grid using FlatList component of the react-native library. I am trying to insert images inside the grids formed inside the FlatList component, but when I am trying to insert the images, the images do not completely fill the particular grid, ther is always the down part of the image which is not displayed in the grid.
Code for the component:
import React, { Component } from 'react';
import { View , StyleSheet, FlatList, Text, Dimensions, Image } from 'react-native';
export const HomeGrid = () => {
return (
<FlatList
data={data}
renderItem={({item}) => (
<View style={styles.itemContainer}>
<Image
style={{flex: 1, width: size, height: size }}
source = {item.value}
/>
</View>
)}
keyExtractor={item => item.id}
numColumns={numColumns} />
);
}
const data = [
{id: 'a', value: require('../photos/photo3.jpg')},
{id: 'b', value: require('../photos/photo2.jpeg')},
{id: 'c', value: require('../photos/photo4.jpg')},
{id: 'd', value: require('../photos/photo3.jpg')},
{id: 'e', value: require('../photos/photo2.jpeg')},
{id: 'f', value: require('../photos/photo4.jpg')}
];
const numColumns = 2;
const size = Dimensions.get('window').width/numColumns;
const styles = StyleSheet.create({
itemContainer: {
width: size,
height: size,
},
item: {
flex: 1,
backgroundColor: 'lightblue',
}
});
What could be the workaround for this?

Related

React Native Expo (Image Picker) is not displaying the Images

Please help me out with this problem.
I can able to pick the image from my Local storage. In the Console also it is showing, But I cannot able to display it on the screen.
Here is my code.
import * as ImagePicker from "expo-image-picker";
import React, { useState } from "react";
import {
ActivityIndicator,
Button,
FlatList,
Image,
StyleSheet,
Text,
useWindowDimensions,
View
} from "react-native";
import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context";
export default function App() {
const [images, setImages] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const pickImages = async () => {
// No permissions request is necessary for launching the image library
setIsLoading(true);
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
// allowsEditing: true,
allowsMultipleSelection: true,
selectionLimit: 10,
aspect: [4, 3],
quality: 1,
});
setIsLoading(false);
console.log(result);
if (!result.canceled) {
setImages(result.uri ? [result.uri] : result.selected);
}
};
return (
<>
<FlatList
data={images}
renderItem={({ item }) => (
<Image
source={{ uri: item.uri }}
style={{ width: 100, height: 100 }}
/>
)}
keyExtractor={(item) => item.uri}
contentContainerStyle={{ marginVertical: 50, paddingBottom: 50 }}
ListHeaderComponent={
isLoading ? (
<View>
<Text
style={{ fontSize: 20, fontWeight: "bold", textAlign: "center" }}
>
Loading...
</Text>
<ActivityIndicator size={"large"} />
</View>
) : (
<Button title="Pick images" onPress={pickImages} />
)
}
/>
</>
);
}
I can able to pick the image from my Local storage. In Console also it is showing, But i cannot able to display it in screen.
Kindly help me out.
It looks like you're already passing the uri into the array. by doing [result.uri] and then in the image you're doing it again item.uri. trying just doing the item.

React Quill is rendering multiple times when it has the onChange method using React

I'm facing an issue with react-quill lib where the component calls itself or I don't know what it calls but I see it on the console, over 500 times and freezes my screen until the loops are done.
Here is the component:
//#ts-nocheck
import ReactQuill from 'react-quill';
import 'react-quill/dist/quill.snow.css';
import './Editor.local.css';
const Editor = ({ method, ...props }: any): any => {
return (
<pre style={{ width: '100%', marginBottom: '5em' }}>
<label className="llabel">{props.label}</label>
<ReactQuill
style={{ height: '420px', borderRadius: '0px 0px 8px 8px' }}
value={props.value}
onChange={method}
modules={Editor.modules}
formats={Editor.formats}
bounds={'#root'}
placeholder={props.placeholder}
/>
</pre>
);
};
Editor.modules = {
toolbar: [
[{ header: [1, 2, 3, 4, 5, 6, false] }],
['bold', 'italic', 'underline'],
[{ list: 'ordered' }, { list: 'bullet' }],
['link'],
['clean']
],
clipboard: {
matchVisual: false,
},
};
export default Editor;
And here Is how i map it and call it multiple times based on the list length:
//#ts-nocheck
import { Item } from '../..';
import { WorkItemValidation } from '../../../../utils/Validation';
import { Date, Input } from '../../../Shared';
import { Editor } from '../../..';
import { Items } from '../Components';
import { Container, Liner, Linerier } from './Components'
import { useState } from 'react';
import { Employment as Work } from '../../../../operations/Resume';
const Employment: any = (props: any) => {
const [isDatePickerOpen, setIsDatePickerOpen] = useState(false);
const handleDescription = (e: any, index: number) => Work.Description(props, index, e);
return (
<Container>
<Items>
{
props.resume.employmentHistory.positions.map(
(position: any, index: number) => {
const title = Work.Show(
position.jobTitle || '',
position.employerName || '',
position.startDate.date || '',
position.endDate.date || '',
position.isCurrent || false
);
const isBoxError = WorkItemValidation(
position.employerName,
position.jobTitle,
position.startDate.date,
position.endDate.date,
position.isCurrent
);
return (
<Item>
<Editor
label="Description"
index={index}
value={position.description && position.description || ''}
placeholder="Brief description of the role..."
method={(e) => handleDescription(e, index)}
/>
</Item>
)
}
)
}
</Items>
</Container >
)
}
export default Employment;
So i don't know what or why, but when i console log inside the editor or the loop i see that this is called many times, over 500 or more or less based on the length of the array and the description.

image is not showing in emulator react native

i have list in which i want to show image like this
this is my list component I have giving correct path but nothin happens have giving width and height but no luck
import React from "react";
import {
View,
Text,
StyleSheet,
Button,
Image,
ImageBackground,
} from "react-native";
import colors from "../config/colors";
import AppText from "./AppText";
export default function ListItem({ image, title, sutitle }) {
return (
<View style={styles.container}>
<Image style={styles.image} source={image} />
<View style={styles.tittleContainer}>
<AppText style={styles.title}>{title}</AppText>
<AppText style={styles.subtitle}>{sutitle}</AppText>
</View>
</View>
);
}
const styles = StyleSheet.create({
image: {
width: 70,
height: 70,
borderRadius: 35,
marginRight: 10,
},
container: {
flexDirection: "row",
},
sutitle: {
fontWeight: "bold",
color: colors.red,
},
tittleContainer: {
padding: 20,
},
title: {
fontWeight: "bold",
marginBottom: 7,
},
});
I am unable to render image on my screen
the issue is while providing props to ListItem component you're passing "Image". and while using it in the component you're using "image".
I hope this solves your issue.
Image is working copy past your code nothing else,
check your image path correctly
https://snack.expo.io/#jsfit/image
export default function ListItem({ image, title, sutitle }) { in this params you are getting the image as lower i and when you are passing with Image as capital I.

React Native: Saving image URI via AsyncStorage and reloading in different React Navigation screen

I am currently trying to combine a React Native Camera example with the React Navigation v2 and want to take a picture in the first view (called CameraView), save said picture to AsyncStorage, navigate to a second view (called GalleryView) and render this picture from AsyncStorage into an image tag.
I am using RN 0.57.1, RN-Camera 1.3.1, React Navigation 2.18.0 on a Windows 10 computer emulating an Android phone running Android version 8.0.0.
This is the code for the two views:
CameraView.js:
import React from "react";
import {
AsyncStorage,
Dimensions,
StyleSheet,
TouchableHighlight,
View
} from "react-native";
import { RNCamera as Camera } from "react-native-camera";
const styles = StyleSheet.create({
preview: {
flex: 1,
justifyContent: "flex-end",
alignItems: "center",
height: Dimensions.get("window").height,
width: Dimensions.get("window").width
},
capture: {
width: 70,
height: 70,
borderRadius: 35,
borderWidth: 5,
borderColor: "#FFF",
marginBottom: 15
}
});
class CameraView extends React.Component {
static navigationOptions = ({ navigation }) => ({
header: null
});
constructor(props) {
super(props);
this.state = {
imageUri: null
};
}
takePicture = async () => {
try {
const imageData = await this.camera.takePictureAsync({
fixOrientation: true
});
this.setState({
imageUri: imageData.uri
});
this._saveImageAsync();
} catch (err) {
console.log("err: ", err);
}
};
_saveImageAsync = async () => {
await AsyncStorage.setItem("imageUri", this.state.imageUri);
this.props.navigation.navigate("GalleryView");
};
render() {
return (
<Camera
ref={cam => {
this.camera = cam;
}}
style={styles.preview}
flashMode={Camera.Constants.FlashMode.off}
permissionDialogTitle={"Permission to use camera"}
permissionDialogMessage={
"We need your permission to use your camera phone"
}
>
<TouchableHighlight
style={styles.capture}
onPress={this.takePicture.bind(this)}
underlayColor="rgba(255, 255, 255, 0.5)"
>
<View />
</TouchableHighlight>
</Camera>
);
}
}
export default CameraView;
GalleryView.js:
import React from "react";
import {
AsyncStorage,
Button,
Dimensions,
StyleSheet,
Text,
Image,
View
} from "react-native";
const styles = StyleSheet.create({
preview: {
flex: 1,
justifyContent: "flex-end",
alignItems: "center",
height: Dimensions.get("window").height,
width: Dimensions.get("window").width
},
cancel: {
position: "absolute",
right: 20,
top: 20,
backgroundColor: "transparent",
color: "#FFF",
fontWeight: "600",
fontSize: 17
}
});
class GalleryView extends React.Component {
static navigationOptions = ({ navigation }) => ({
title: "Seismic"
});
constructor(props) {
super(props);
AsyncStorage.getItem("imageUri").then(response => {
this.setState({
imageUri: response
});
});
}
render() {
return (
<View>
<Image source={{ uri: this.state.imageUri }} style={styles.preview} />
<Text
style={styles.cancel}
onPress={() => this.state.setState({ imageData: null })}
>
X
</Text>
<Button
title="Map View"
onPress={() => this.props.navigation.popToTop()}
/>
</View>
);
}
}
export default GalleryView;
The first-mentioned example works fine, but when trying to use the AsyncStorage I get the error below after snapping the image and executing navigate() to the second view.
TypeError: TypeError: null is not an object (evaluating
'this.state.imageUri')
This error is located at:
in GalleryView (at SceneView.js:9)
in SceneView (at StackViewLayout.js:478)
in RCTView (at View.js:44)
in RCTView (at View.js:44)
in RCTView (at View.js:44)
in AnimatedComponent (at screens.native.js:58)
in Screen (at StackViewCard.js:42)
in Card (at createPointerEventsContainer.js:26)
in Container (at StackViewLayout.js:507)
in RCTView (at View.js:44)
in ScreenContainer (at StackViewLayout.js:401)
in RCTView (at View.js:44)
in StackViewLayout (at withOrientation.js:30)
in withOrientation (at StackView.js:49)
in RCTView (at View.js:44)
in Transitioner (at StackView.js:19)
in StackView (at createNavigator.js:57)
in Navigator (at createKeyboardAwareNavigator.js:11)
in KeyboardAwareNavigator (at createNavigationContainer.js:376)
in NavigationContainer (at routes.js:39)
in Routes (at renderApplication.js:34)
in RCTView (at View.js:44)
in RCTView (at View.js:44)
in AppContainer (at renderApplication.js:33)
>
This error is located at:
in NavigationContainer (at routes.js:39)
in Routes (at renderApplication.js:34)
in RCTView (at View.js:44)
in RCTView (at View.js:44)
in AppContainer (at renderApplication.js:33) render
C:\Users\msteinbrink\Safeguard\seismic-app\src\screens\GalleryView.js:25:11
proxiedMethod
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-proxy\modules\createPrototypeProxy.js:44:35
finishClassComponent
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:10563:21
updateClassComponent
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:10505:4
beginWork
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:11338:8
performUnitOfWork
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:14091:21
workLoop
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:14129:41
renderRoot
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:14226:15
performWorkOnRoot
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:15193:17
performWork
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:15090:24
performSyncWork
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:15047:14
requestWork
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:14925:19
scheduleWork
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:14711:16
enqueueSetState
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:7700:17
setState
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react\cjs\react.development.js:372:31
dispatch
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-navigation\src\createNavigationContainer.js:342:22
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-navigation\src\getChildNavigation.js:56:33
_callee2$
C:\Users\msteinbrink\Safeguard\seismic-app\src\screens\CameraView.js:88:16
tryCatch
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\#babel\runtime\node_modules\regenerator-runtime\runtime.js:62:44
invoke
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\#babel\runtime\node_modules\regenerator-runtime\runtime.js:288:30
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\#babel\runtime\node_modules\regenerator-runtime\runtime.js:114:28
tryCatch
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\#babel\runtime\node_modules\regenerator-runtime\runtime.js:62:44
invoke
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\#babel\runtime\node_modules\regenerator-runtime\runtime.js:152:28
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\#babel\runtime\node_modules\regenerator-runtime\runtime.js:162:19
tryCallOne
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\promise\setimmediate\core.js:37:14
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\promise\setimmediate\core.js:123:25
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Core\Timers\JSTimers.js:295:23
_callTimer
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Core\Timers\JSTimers.js:152:14
_callImmediatesPass
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Core\Timers\JSTimers.js:200:17
callImmediates
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Core\Timers\JSTimers.js:464:30
__callImmediates
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:320:6
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:135:6
__guard
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:297:10
flushedQueue
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:134:17
invokeCallbackAndReturnFlushedQueue
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:130:11
I would appreciate if someone could point out how to properly use AsyncStorage with React Navigation to render a previously saved image from React Native Camera. As you probably could tell, I am fairly new to React Native, so please tell me if I got the concept completely wrong or anything.
Thanks in advance!
Thanks to Wainages comment, I made it work. I added the state isLoaded in GalleryView and show just the text "Loading" before the async operation is done.
import React from "react";
import {
AsyncStorage,
Dimensions,
StyleSheet,
Text,
Button,
Image,
View
} from "react-native";
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
backgroundColor: "#000000"
},
preview: {
flex: 1,
justifyContent: "flex-end",
alignItems: "center",
height: Dimensions.get("window").height,
width: Dimensions.get("window").width
},
cancel: {
position: "absolute",
right: 20,
top: 20,
backgroundColor: "transparent",
color: "#FFF",
fontWeight: "600",
fontSize: 17
}
});
class GalleryView extends React.Component {
static navigationOptions = ({ navigation }) => ({
title: "Seismic"
});
constructor(props) {
super(props);
this.state = {
imageUri: null,
isLoaded: false
};
AsyncStorage.getItem("imageUri").then(response => {
this.setState({
isLoaded: true,
imageUri: response
});
});
}
renderImage() {
return (
<View>
<Image source={{ uri: this.state.imageUri }} style={styles.preview} />
<Text
style={styles.cancel}
onPress={() => this.setState({ path: null })}
>
X
</Text>
</View>
);
}
renderLoadingScreen() {
return (
<View>
<Text style={styles.cancel}>Loading</Text>
<Button
title="Map View"
onPress={() => this.props.navigation.popToTop()}
/>
</View>
);
}
render() {
return (
<View style={styles.container}>
{this.state.isLoaded ? this.renderImage() : this.renderLoadingScreen()}
</View>
);
}
}
export default GalleryView;

Easy way to add a drawer item with custom onPress?

I'm using DrawerNavigator and, as long as I want to navigate to a new screen, all's fine.
Now I want to add a drawer item which does not navigate to a new screen but simply triggers an action (in general). Specifically, I want to use 'react-native' Share functionality.
I got this to work but I think the solution is not a very good one. Here's what I got so far:
const myContentComponent = props => (
<ScrollView alwaysBounceVertical={false}>
<SafeAreaView style={{ flex: 1 }} forceInset={{ top: 'always', horizontal: 'never' }}>
<DrawerItems {...props} />
<TouchableItem
key="share"
onPress={() => {
Share.share(
{
message: 'YO: this will be the text message',
url: 'http://tmp.com',
title: 'This will be the email title/subject',
},
{
// Android only:
dialogTitle: 'This will be the title in the dialog to choose means of sharing',
},
);
props.navigation.navigate('DrawerClose');
}}
delayPressIn={0}
>
<SafeAreaView forceInset={{ left: 'always', right: 'never', vertical: 'never' }}>
<View style={[{ flexDirection: 'row', alignItems: 'center' }, {}]}>
<View style={[{ marginHorizontal: 16, width: 24, alignItems: 'center' }, { opacity: 0.62 }, {}]}>
<Icon name="share" />
</View>
<Text style={[{ margin: 16, fontWeight: 'bold' }, { color: DrawerItems.defaultProps.inactiveTintColor }]}>Share</Text>
</View>
</SafeAreaView>
</TouchableItem>
</SafeAreaView>
</ScrollView>
);
const RootStack = DrawerNavigator(
{
Settings: {
screen: SettingsScreen,
},
},
{
contentComponent: myContentComponent,
},
);
Basically, I am creating a new contentComponent based off of the default:
https://github.com/react-navigation/react-navigation/blob/v1.5.8/src/navigators/DrawerNavigator.js#L16-L22
I am copying the styles and element structure of a normal drawer item (everything under TouchableItem) - all this so I can define my own onPress which does the share logic and closes the drawer.
There has to be a better way right? What happens if I want the "Share" drawer item somewhere amongst the drawer items rendered by DrawerItems (the ones that support navigation)? Right now I can only work around the items rendered by DrawerItems. Besides, copying so much code from react-navigation seems like really bad form.
I just want an item which does some custom logic instead of rendering a screen.
I am not sure will it be helpful?
I used onPress event for logout like this way. It's no need to render a new DrawerItems
const DrawerNavigator = createAppContainer(createDrawerNavigator({
Logout: {
screen: EmptyScreenForLogoutConfirmation,
navigationOptions: ({ navigation }) => ({
tabBarLabel: 'Logout',
drawerIcon: ({ tintColor }) => <Icon name={"ios-cog"} size={26} />,
}),
},
},
{
contentComponent:(props ) => (
<DrawerItems {...props}
onItemPress = {
( route ) =>
{
if (route.route.routeName !== "Logout") {
props.onItemPress(route);
return;
}
return Alert.alert( // Shows up the alert without redirecting anywhere
'Confirmation required'
,'Do you really want to logout?'
,[
{text: 'No'},
{text: 'Yes', onPress: () => { props.navigation.navigate('Logedout'); }},
]
)
}
}
/>
),
contentOptions: {
activeTintColor: '#e91e63',
}
},))

Resources