How To Implement Auto Scrolling Video in React Native using JSX - javascript

import React, {useState, useEffect, useRef} from 'react';
import {
View,
Text,
StyleSheet,
FlatList,
ScrollView,
Image,
TouchableHighlight,
TextInput,
TouchableOpacity,
Modal,
Dimensions,
SafeAreaView,
} from 'react-native';
import Voice from 'react-native-voice';
import Video from 'react-native-video';
import SimpleLineIcons from 'react-native-vector-icons/SimpleLineIcons';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import {videos} from './data';
// code started creating state on every event which will be used
enter center export default function App() {
const [pitch, setPitch] = useState('');
const [error, setError] = useState('');
const [end, setEnd] = useState('');
const [started, setStarted] = useState('');
const [results, setResults] = useState([]);
const [videoData, setVideos] = useState([...videos]);
const [showModal, setShowModal] = useState(false);
const [paused, setPaused] = useState(true);
const [position, setPosition] = useState({start: null, end: null});
const [muted, setMuted] = useState(true);
//Setting callbacks for the process status
useEffect(() => {
Voice.onSpeechStart = onSpeechStart;
Voice.onSpeechEnd = onSpeechEnd;
Voice.onSpeechError = onSpeechError;
Voice.onSpeechResults = onSpeechResults;
return () => {
//destroy the process after switching the screen
Voice.destroy().then(Voice.removeAllListeners);
};
}, []);
const onSpeechStart = (e) => {
//Invoked when .start() is called without error
console.log('onSpeechStart: ', e);
setStarted('√');
};
const onSpeechEnd = (e) => {
//Invoked when SpeechRecognizer stops recognition
console.log('onSpeechEnd: ', e);
setEnd('√');
};
const onSpeechError = (e) => {
//Invoked when an error occurs.
console.log('onSpeechError: ', e);
setError(JSON.stringify(e.error));
};
2. in this part we are matching the word sopken by the user and checking is if the same video is available in our data if it si then the video will come on the top
const onSpeechResults = (e) => {
//Invoked when SpeechRecognizer is finished recognizing
console.log('onSpeechResults: ', e.value[0]);
let vResult = e.value[0];
let small = vResult.toLowerCase();
setResults([small]);
setShowModal(false);
for (let i = 0; i < videoData.length - 1; i++) {
let newArray = [...videos];
if (small == newArray[i].name) {
newArray.splice(0, 0, newArray[i]);
const mainArray = newArray.filter((item, index) => {
if (item.name == small && index != 0) {
} else {
return item;
}
});
setVideos(mainArray);
}
}
};
const startRecognizing = async () => {
console.log('start listenind');
//Starts listening for speech for a specific locale
try {
await Voice.start('en-US');
setPitch('');
setError('');
setStarted('');
setResults([]);
setEnd('');
} catch (e) {
//eslint-disable-next-line
console.error(e);
}
};
const stopRecognizing = async () => {
//Stops listening for speech
try {
await Voice.stop();
} catch (e) {
//eslint-disable-next-line
console.error(e);
}
};
3. making video play n pause is out of axis
onScroll = (event) => {
const scrollPosition = event.nativeEvent.contentOffset.y;
const paused = paused;
const {start, end} = position;
if (scrollPosition < start && scrollPosition > end && paused) {
setPaused(false);
} else if (scrollPosition > start && scrollPosition < end && !paused) {
setPaused(true);
} else if (scrollPosition < end && !paused) {
setPaused(true);
}
};
4. getting the scroll y axis
const threshold = 180;
onVideoLayOut = (event) => {
const {height} = Dimensions.get('window');
const start = -(event.nativeEvent.layout.y - height + threshold);
const end =
event.nativeEvent.layout.y + event.nativeEvent.layout.height - threshold;
// console.log(start, end, 'position');
setPosition((state) => {
return {
...state,
start: start,
end: end,
};
});
console.log(position, 'position1');
};
5.this the render par using faltlist to render data
return (
<View
style={{
flex: 1,
backgroundColor: 'black',
}}>
<View
style={{
height: 70,
alignItems: 'center',
justifyContent: 'space-between',
marginHorizontal: 15,
flexDirection: 'row',
marginVertical: 15,
marginTop: 25,
}}>
<View
style={{
height: 40,
borderRadius: 20,
width: 300,
borderWidth: 1,
borderColor: '#F23C29',
}}>
<TextInput
placeholder="Search ..."
style={{flex: 1, paddingHorizontal: 30, color: 'white'}}
placeholderTextColor="grey"
/>
</View>
<View>
<TouchableOpacity
onPress={() => {
startRecognizing();
setShowModal(true);
}}>
<SimpleLineIcons color={'white'} name="microphone" size={30} />
</TouchableOpacity>
</View>
</View>
<SafeAreaView
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
borderColor: 'orange',
borderWidth: 1,
}}>
<FlatList
data={videoData}
// scrollEventThrottle={16}
onScroll={onScroll}
showsVerticalScrollIndicator={true}
renderItem={({item, index}) => {
return (
<View
key={index}
style={{
height: 250,
marginVertical: 20,
}}>
<Video
source={{uri: item.source}}
onLayout={onVideoLayOut}
muted={true}
resizeMode="cover"
paused={!paused}
style={{
width: '100%',
height: undefined,
aspectRatio: 2,
marginBottom: 200,
marginTop: 300,
}}
/>
<Text
style={{
fontSize: 20,
alignItems: 'center',
marginLeft: 20,
marginTop: 15,
color: 'white',
}}>
{item.title}
</Text>
</View>
);
}}
/>
</SafeAreaView>
{/* <ScrollView style={{flex: 2, width: '100%'}}>
{videoData.map((item, index) => {
return (
<View
key={index}
style={{
height: 250,
marginVertical: 20,
}}>
<Video
source={{uri: item.source}}
paused={false}
rate={1.0}
volume={1.0}
isMuted={false}
resizeMode="contain"
shouldPlay
isLooping
style={{width: '100%', height: undefined, aspectRatio: 2}}
onError={(e) => {
console.log(e, 'video data');
}}
/>
<Text
style={{
fontSize: 20,
alignItems: 'center',
marginLeft: 20,
marginTop: 15,
color: 'white',
}}>
{item.title}
</Text>
</View>
);
})}
</ScrollView> */}
<Modal
visible={showModal}
transparent={true}
onRequestClose={() => {
setShowModal(false);
}}>
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0,0,0,0.9)',
}}>
<MaterialCommunityIcons
name="microphone-settings"
size={45}
color="white"
/>
<Text
style={{
color: '#fff',
textAlign: 'center',
marginTop: 20,
fontSize: 17,
}}>
We are listening
</Text>
</View>
</Modal>
{/* <View style={{justifyContent: 'center', alignItems: 'center'}}>
<Text>Video</Text>
<View>
<TouchableHighlight
onPress={stopRecognizing}
style={styles.buttonStyle}>
<Text style={styles.buttonTextStyle}>Stop</Text>
</TouchableHighlight>
</View>
<View>
<TouchableHighlight onPress={startRecognizing}>
<SimpleLineIcons name="microphone" size={25} />
</TouchableHighlight>
</View>
{results.map((item, index) => {
return (
<Text key={`result-${index}`} style={styles.textStyle}>
{item}
</Text>
);`enter code here`
})}
<Text>Results</Text>
</View> */}
</View>
);
}
const styles = StyleSheet.create({
backgroundVideo: {
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
},
});
The question is in my flat list at a time, there are three videos which are render .. I was trying to make the first video play and rest to be in paused state and after a 5 second of interval, the next video should be played
I tried demo which looks like instagram where the video which is in focused is played automatically and rest all are paused
I tried using scroll props and also video-autoscroll lib but coudlnot resolve
the videos are getting render but

Related

Displaying a Image from the Camera

I am relatively new to React-Native and mobile app development. I am trying to create a clone of Instagram. And in the post screen what I do is I have a button Camera and once I click on it, that should take me to CameraView screen. And in the CameraView screen I will take a picture using expo-camera and save the picture in a variable. So here, I want to export the picture and then import it in my Post screen, so that the user can have a preview of what the picture looks like before uploading. And another thing to note is that, the Post screen will by default have a Placeholder image and once the image is taken the placeholder image has to be replaced with the image.
I tried this code but it didnt work.
My Post screen :-
import { View, Text, Image, TextInput } from 'react-native';
import React, { useState, useEffect } from 'react'
import * as Yup from 'yup';
import { Formik } from 'formik'
import { Button, Divider } from 'react-native-elements';
import { useNavigation } from '#react-navigation/native';
import CameraView, { takePicture } from '../../screens/CameraView';
const PLACEHOLDER_IMG = require('../../assets/defImg.png')
const uploadPostSchema = Yup.object().shape({
caption: Yup.string().max(2200, 'Caption cannot exceed character limit.')
})
const FormikPostUploader = ({route}) => {
const [thumbnailUrl, setThumbnailUrl] = useState(PLACEHOLDER_IMG)
const navigation = useNavigation()
const handleCameraPress = () => {
UserImage = takePicture()
setThumbnailUrl(UserImage)
navigation.navigate('CameraView')
}
return (
<Formik
initialValues={{ imageUrl: '', caption:'' }}
onSubmit={(values) => console.log(values)}
validationSchema={uploadPostSchema}
validateOnMount={true}>
{({
handleBlur,
handleChange,
handleSubmit,
values,
errors,
isvalid
}) => (
<>
<View style={{ margin: 20, justifyContent: 'space-between', flexDirection: 'row' }}>
<Image source={thumbnailUrl} />
<View style={{ flex: 1, margin: 15 }}>
<TextInput
placeholder='Write a caption...'
placeholderTextColor='gray'
multiline={true}
style={{ color: 'white', fontSize: 17 }}
onChangeText={handleChange('caption')}
onBlur={handleBlur('caption')}
value={values.caption}
/>
</View>
</View>
<Divider width={0.5} orientation='vertical'/>
<View style={{ alignItems: 'center', marginTop: 15 }}>
<Text style={{ fontSize: 18, fontWeight: 'bold', color: 'white' }}>Choose Image</Text>
</View>
<View style={{ justifyContent: 'space-between', flexDirection: 'column', margin: 20 }}>
<View style={{ justifyContent: 'space-between', flexDirection: 'row', margin: 30 }}>
<Button title='Camera' onPress={handleCameraPress}/>
<Button title='Gallery' onPress={() => navigation.navigate('GalleryView')} />
</View>
<Button onPress={handleSubmit} title='Post' disabled={isvalid} />
</View>
</>
)}
</Formik>
)
}
export default FormikPostUploader
And my CameraView screen :-
import { View, Text, Image, StyleSheet, Button } from 'react-native'
import React, {useState, useEffect} from 'react'
import { Camera } from 'expo-camera'
import { TouchableOpacity } from 'react-native'
import { useNavigation } from '#react-navigation/native'
import { PLACEHOLDER_IMG } from '../components/newPost/FormikPostUploader'
export const takePicture = async(camera) => {
const data = await camera.takePictureAsync(null)
return data.uri
}
const Header = () =>{
const navigation = useNavigation()
return (
<View style = {styles.headerContainer}>
<TouchableOpacity style = {{marginBottom:15}} onPress={() => navigation.goBack()}>
<Image source = {require('../assets/back.png')} style = {{width:35, height:35, margin:20}}/>
</TouchableOpacity>
<Text style={{color:'white', fontWeight: '700', fontSize:20, marginRight: 25, marginTop:35, marginBottom:15}}>New Post</Text>
<Text> </Text>
</View>
)
}
const CameraView = () => {
const UserImage = takePicture()
const navigation = useNavigation()
const [hasCameraPermission, setHasCameraPermission] = useState(null)
const [thumbnailUrl, setThumbnailUrl] = useState(PLACEHOLDER_IMG)
const [camera, setCamera] = useState(null)
const [type, setType] = useState(Camera.Constants.Type.back)
const captureImage = async () => {
if (camera) {
const UserImage = await takePicture(camera)
setThumbnailUrl(UserImage)
}
}
useEffect(() => {
(async() => {
const cameraStatus = await Camera.requestCameraPermissionsAsync()
setHasCameraPermission(cameraStatus.status === 'granted')})()},
[])
if (hasCameraPermission === null) {
return <View/>
}
if (hasCameraPermission === false){
return <Text>Enable access for Camera to proceed</Text>
}
return (
<View style={{ flex: 1, backgroundColor: 'black'}}>
<Header/>
<Camera
ref = {ref => setCamera(ref)}
style={styles.fixedRatio}
type={type}
ratio={'1:1'}/>
<View style = {styles.cameraContainer}>
<TouchableOpacity onPress={() => {setType(type === Camera.Constants.Type.back ? Camera.Constants.Type.front : Camera.Constants.Type.back)}}>
<Image source={require('../assets/turn-camera.png')} style = {{width:70, height:70, margin: 15}}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => {captureImage(), navigation.goBack(), console.log(UserImage)}}>
<Image source={require('../assets/camera-shutter.png')} style = {{width:70, height:70, marginRight:60}}/>
</TouchableOpacity>
</View>
</View>
)
}
const styles = StyleSheet.create({
cameraContainer: {
flex:0.15,
backgroundColor: 'black',
flexDirection:'row',
justifyContent: 'space-between',
alignItems: 'center',
},
fixedRatio: {
flex:0.99,
aspectRatio:0.9
},
headerContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
backgroundColor:'black'
},
icon: {
width:25,
height: 25,
marginHorizontal:15,
marginTop:30,
},
iconContainer: {
flexDirection:'row',
justifyContent: 'space-between',
height:50,
},
}
)
export default CameraView
Am I doing anything wrong. Can you help me fix this. Thanks in advance!

React-Native expo modal with textinput, Keyboard and modal flicker after every text entry unable to input text

I have an issue with modal not being stable when text input receives entry. I have struggled with this and read most post on this site but when I try it, no results. One of them is Keyboard closes after every keypress in TextInput react native. I have taken most of the irrelevant code out so you have an idea of what I want to achieve. It's quiet lengthy but I tried.
import React, { useEffect, useState } from "react";
/*
loads of imports
**/
const ReplyFeedback = (props) => {
const [dataset, setdataset] = useState([]);
const [replyset, setreplyset] = useState([]);
const [visible, setvisible] = useState(null);
const [messagereply, setmessagereply] = useState("");
const [msgid, setmsgid] = useState(null);
const dispatch = useDispatch();
/**
* useEffects and functions
*/
const handleSaveReply = (id) => {
/**
* Saving the reply from text input for firebase
*/
};
const handleCaseupdate = async () => {
/**
* Some firebase events
*/
};
function processreply(id) {
setmsgid(id);
setvisible(true);
}
const renderfeedback = (id, message, date, index) => (
/**
* reder some jsx
*/
);
const renderreply = (item, index) => (
/**
* render some jsx
*/
);
const ModalPopup = ({ visible, children }) => {
const [showmodal, setshowmodal] = useState(visible);
const togglemodal = () => {
if (visible) {
setshowmodal(true);
} else {
setshowmodal(false);
}
};
return (
<Modal transparent visible={showmodal}>
<View
style={{
flex: 1,
backgroundColor: "rgba(0,0,0,0.5)",
justifyContent: "center",
alignItems: "center",
}}
>
<View style={styles.modalContainer}>{children}</View>
</View>
</Modal>
);
};
return (
<React.Fragment>
<SafeAreaView style={styles.container}>
<KeyboardAvoidingView behavior="position">
<ModalPopup visible={visible}>
<View
style={{
width: "90%",
height: "72%",
backgroundColor: "rgb(255,255,255)",
}}
>
<View
style={{
flexDirection: "row",
justifyContent: "center",
}}
>
<TextInput
placeholder="Enter Reply"
multiline
autoCorrect
scrollEnabled
numberOfLines={8}
autoCapitalize="sentences"
placeholderTextColor="rgb(0,191,255)"
onChangeText={(text) => setmessagereply(text)}
value={messagereply}
blurOnSubmit={false}
style={{
width: "100%",
height: 250,
fontSize: 20,
padding: 10,
textAlignVertical: "top",
backgroundColor: "rgb(245,245,245)",
}}
/>
</View>
<View
style={{
marginTop: 15,
flexDirection: "row",
justifyContent: "space-around",
}}
>
<TouchableOpacity
style={{
width: 65,
height: 65,
borderRadius: 30,
alignItems: "center",
justifyContent: "center",
backgroundColor: "rgb(109, 123, 175)",
}}
onPress={() => setvisible(false)}
>
<MaterialIcons
name="cancel"
size={50}
color="rgb(225,225,225)"
/>
</TouchableOpacity>
<TouchableOpacity
onPress={() => handleSaveReply(msgid)}
style={{
width: 65,
height: 65,
borderRadius: 30,
alignItems: "center",
justifyContent: "center",
backgroundColor: "rgb(109, 123, 175)",
}}
>
<Ionicons name="send" size={40} color="rgb(255,255,255)" />
</TouchableOpacity>
</View>
</View>
</ModalPopup>
</KeyboardAvoidingView>
<View style={styles.feedbackreply}>
<View style={styles.replydetails}>
{/**
* some jsx
*/}
</View>
{/**
* somejsx
*/}
</View>
<View
style={{
alignSelf: "flex-end",
marginHorizontal: 5,
marginTop: 5,
}}
>
{/**
* some jsx
*/}
</View>
<ScrollView
automaticallyAdjustContentInsets={false}
keyboardShouldPersistTaps="handled"
>
{dataset &&
dataset
.sort(
(a, b) =>
new moment(new Date(a.date)).format("YYYYMMDD HHmmss") -
new moment(new Date(b.date)).format("YYYYMMDD HHmmss")
)
.map(({ id, message, date }, index) =>
renderfeedback(id, message, date, index)
)}
<ScrollView keyboardShouldPersistTaps="handled">
{replyset &&
replyset
.sort(
(a, b) =>
new moment(new Date(a.date)).format("YYYYMMDD HHmmss") -
new moment(new Date(b.date)).format("YYYYMMDD HHmmss")
)
.filter((item) => item.id !== id)
.map((item, index) => renderreply(item, index))}
</ScrollView>
</ScrollView>
</SafeAreaView>
</React.Fragment>
);
};
export { ReplyFeedback };
const window = Dimensions.get("window");
const styles = StyleSheet.create({
/**
* Tones of styling
*/
});
So you could see from the container I rendered some other views including a scrollview that all appears under the modal when it is shown. Please the issue here is that the modal flickers along with the keyboard making it impossible to add text
This is the image

Issue with updating an array in React Native

I am trying to work through a problem with my array state in React Native and correctly updating the array of objects when I click a button on one of the components.
Here is a video of the problem occurring, which is probably a better way to explain the issue: https://cdn.discordapp.com/attachments/935693286566416417/953045147397001276/RPReplay_Final1647294055.MP4
Here's the relevant code that might offer some insight:
MealPlanner.Js
const MealPlannerScreen = props => {
const minDate = new Date();
const [mealPlannerData, setMealPlannerData] = useState([]);
const [loading, setLoading] = useState(true)
const [selectedDate, setSelectedDate] = useState("03/13/2022")
const [breakfast, setBreakfast] = useState([])
const getMealPlannerData = async(date = '03/13/2022') => {
const isDataAvailable = await AsyncStorage.getItem("meal_planner")
if (isDataAvailable) {
const parsedData = JSON.parse(isDataAvailable)
let breakfastData = parsedData.filter(function (e) {
return ((e.date = date) && (e.meal == 'Breakfast'));
});
let lunchData = parsedData.filter(function (e) {
return ((e.date = date) && (e.meal == 'Lunch'));
});
let dinnerData = parsedData.filter(function (e) {
return ((e.date = date) && (e.meal == 'Dinner'));
});
let snacksData = parsedData.filter(function (e) {
return ((e.date = date) && (e.meal == 'Snacks'));
});
setMealPlannerData(JSON.parse(isDataAvailable))
setBreakfast(breakfastData)
setLunch(breakfastData)
setDinner(dinnerData)
setSnacks(snacksData)
} else {
setMealPlannerData([])
}
}
const childToParent = async(unique_id, meal, date) => {
const mealFiltered = mealPlannerData.filter(function (e) {
return e.unique_id != unique_id;
});
console.log(unique_id)
console.log(date)
if (meal === 'Breakfast') {
let breakfastData = mealFiltered.filter(function (e) {
return ((e.date = date) && (e.meal == 'Breakfast'));
});
console.log(breakfastData);
setBreakfast(breakfastData)
}
return (
<Container style={styles.background_general}>
<View>
{breakfast.map((p, i) => {
console.log(breakfast)
return (<>
<FoodItem meal={"Breakfast"} date={p.date} food={p.recipe_name} calories={p.calories} servings={p.servings} unique_id={p.unique_id} mealData={mealPlannerData} childToParent={childToParent}/>
<View style={{
borderBottomColor: 'rgba(0,0,0,0.1)',
borderBottomWidth: 1,
}}>
</View>
</>
)
})}
</View>
</Container>
}
}
And the FoodItem.js
const FoodItem = props => {
removeMeal = (unique_id, meal) => {
props.childToParent(unique_id, meal, props.date)
}
const renderRightActions = useCallback((progress, dragX) => {
const trans = dragX.interpolate({
inputRange: [-300, -160, 0],
outputRange: [0, 0, 160],
});
return (
<Animated.View
style={{
transform: [{ translateX: trans }],
}}
>
<LinearGradient
colors={["#6e269b", "#35184e"]}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
style={{
flexDirection: "row",
width: 160,
height: "100%",
borderRadius: 20
}}
>
<RectButton style={{
justifyContent: "center",
alignItems: "center",
paddingHorizontal: 16,
flex: 1
}} onPress={() => {removeMeal(props.unique_id, props.meal) }}>
<View style={{ flexDirection: 'row' }}>
<Icon type="FontAwesome" name="trash" style={{ fontSize: 18, color: 'white', paddingRight: 10, marginTop: 2 }} />
<Text style={{ color: '#fff', fontWeight: 'bold', fontSize: 18 }}>
Remove
</Text>
</View>
</RectButton>
</LinearGradient>
</Animated.View>);
}, []);
return (
<View style={{
padding: 20
}}>
<Swipeable renderRightActions={renderRightActions}>
<View padding-6 row>
<View style={{ alignItems: "center" }}>
</View>
<View >
<Text style={{ fontSize: 18, fontWeight: 'bold' }}>
{props.food}
</Text>
<View row marginT-8>
<View row>
<Text R14 color6D marginL-4>
{props.calories} cal
</Text>
</View>
<View row marginL-24>
<Text R14 color6D marginL-4>
{props.servings} servings
</Text>
</View>
</View>
</View>
</View>
</Swipeable>
</View>
)
}
Any help would be greatly appreciated!

How to save route.params with asyncstorage?

Srry if the title makes no sense. Don't know a better title.
How can I save route.params items that I pass to my second screen using AsyncStorage?
In my first screen i have a bunch of data in a FlatList that can be opened with a Modal. Inside that Modal I have a TouchableOpacity that can send the data thats inside the Modal to my second screen. The data that has been passed to the second screen is passed to a FlatList. The data in the FlatList should be saved to AsyncStorage. Tried alot of things getting this to work, but only getting warning message
undefined. Code below is the most recent progress.
Using React Navigation V5.
FIRST SCREEN
const [masterDataSource, setMasterDataSource] = useState(DataBase);
const [details, setDetails] = useState('');
<TouchableOpacity
onPress={() => {
const updated = [...masterDataSource];
updated.find(
(item) => item.id === details.id,
).selected = true;
setMasterDataSource(updated);
navigation.navigate('cart', {
screen: 'cart',
params: {
items: updated.filter((item) => item.selected),
},
});
setModalVisible(false);
}}>
<Text>Add to cart</Text>
</TouchableOpacity>
SECOND SCREEN
import React, { useEffect, useState } from 'react';
import { View, Text, FlatList, TouchableOpacity } from 'react-native';
import { useTheme } from '../Data/ThemeContext';
import AsyncStorage from '#react-native-async-storage/async-storage';
import Ionicons from 'react-native-vector-icons/Ionicons';
export default function ShoppingList({ route, navigation }) {
const [shoppingList, setShoppingList] = useState([]);
const { colors } = useTheme();
const todo = () => {
alert('Todo');
};
useEffect(() => {
restoreShoppingListAsync();
}, []);
const shoppingListAsync = () => {
const shoppingList = route.params && route.params.items;
setShoppingList(list);
storeShoppingList(list);
};
const asyncStorageKey = '#ShoppingList';
const storeShoppingListAsync = (list) => {
const stringifiedList = JSON.stringify(list);
AsyncStorage.setItem(asyncStorageKey, stringifiedList).catch((err) => {
console.warn(err);
});
};
const restoreShoppingListAsync = () => {
AsyncStorage.getItem(asyncStorageKey)
.then((stringifiedList) => {
console.log(stringifiedList);
const parsedShoppingList = JSON.parse(stringifiedList);
if (!parsedShoppingList || typeof parsedShoppingList !== 'object')
return;
setShoppingList(parsedShoppingList);
})
.then((err) => {
console.warn(err);
});
};
const RenderItem = ({ item }) => {
return (
<View>
<TouchableOpacity
style={{
marginLeft: 20,
marginRight: 20,
elevation: 3,
backgroundColor: colors.card,
borderRadius: 10,
}}>
<View style={{ margin: 10 }}>
<Text style={{ color: colors.text, fontWeight: '700' }}>
{item.name}
</Text>
<Text style={{ color: colors.text }}>{item.gluten}</Text>
<Text style={{ color: colors.text }}>{item.id}</Text>
</View>
</TouchableOpacity>
</View>
);
};
const emptyComponent = () => {
return (
<View style={{ alignItems: 'center' }}>
<Text style={{ color: colors.text }}>Listan är tom</Text>
</View>
);
};
const itemSeparatorComponent = () => {
return (
<View
style={{
margin: 3,
}}></View>
);
};
return (
<View
style={{
flex: 1,
}}>
<View
style={{
padding: 30,
backgroundColor: colors.Textinput,
elevation: 12,
}}>
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
<TouchableOpacity onPress={() => navigation.goBack()}>
<Ionicons name="arrow-back-outline" size={25} color="#fff" />
</TouchableOpacity>
<Text style={{ color: '#fff', fontSize: 20 }}>Inköpslista</Text>
<TouchableOpacity>
<Ionicons
name="trash-outline"
size={25}
color="#fff"
onPress={() => todo()}
/>
</TouchableOpacity>
</View>
</View>
<View style={{ flex: 1, marginTop: 30 }}>
<FlatList
data={shoppingList}
renderItem={RenderItem}
ListEmptyComponent={emptyComponent}
ItemSeparatorComponent={itemSeparatorComponent}
initialNumToRender={4}
maxToRenderPerBatch={5}
windowSize={10}
removeClippedSubviews={true}
updateCellsBatchingPeriod={100}
showsVerticalScrollIndicator={true}
contentContainerStyle={{ paddingBottom: 20 }}
/>
</View>
</View>
);
}
As you are using async storage to maintain the cart.
I would suggest an approach as below
Update the asyn storage when new items are added to or removed from the cart
Retrieve the items from the cart screen and show the items there
Before you navigate store the items like below
AsyncStorage.setItem(
'Items',
JSON.stringify(updated.filter((item) => item.selected))
).then(() => {
navigation.navigate('Cart', {
items: updated.filter((item) => item.selected),
});
});
The cart screen would be something like below
function Cart({ navigation, route }) {
const [data,setData]=useState([]);
React.useEffect(() => {
async function fetchMyAPI() {
const value = await AsyncStorage.getItem('Items');
setData(JSON.parse(value));
}
fetchMyAPI();
}, []);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button title="Go back" onPress={() => navigation.goBack()} />
<FlatList
data={data}
renderItem={RenderItem}
/>
</View>
);
}
Working Example
https://snack.expo.io/#guruparan/cartexample

How can i get back my data list after searching by words?

i use Flatlist and search by words on renderHeader() function. I can filter but when i delete letters, i couldn't get main list again. I think there is a logic problem but i couln't find after trying something...
i've got a new one when i fixed problem. I tried to fix but i couldn't do that, i should put the problem in front of experts :)
import React, {Component, useState} from 'react'
import {
Text,
StyleSheet,
View,
FlatList,
SafeAreaView,
ScrollView,
Image,
TextInput,
} from 'react-native'
import data from '../../data'
const Flatlistexample = () => {
//main list state
let [list, setList] = useState(data);
//search state
const [search, setSearch] = useState('');
//search filter
searchFilter = text => {
// onChangeText
const newData = list.filter(item => {
const listItem = `${item.name.toLowerCase()} ${item.company.toLowerCase()}`
return listItem.indexOf(text.toLowerCase()) > -1;
})
setList(newData)
}
//search function
renderHeader = () =>{
return (
<View style={styles.seachContainer}>
<TextInput
style={styles.textInput}
placeholder={'Search...'}
value={search}
onChangeText={text => {
//setStates
searchFilter(text)
setSearch(text)
}}></TextInput>
<Text
style={{
alignItems: 'flex-start',
color: 'black',
fontSize: 22,
}}>
{search}
</Text>
</View>
)
}
return (
<SafeAreaView
style={{
flex: 1,
}}>
<FlatList
data={list}
renderItem={({item, index}) => {
return (
<ScrollView>
<SafeAreaView
style={[
styles.container,
{backgroundColor: index % 2 === 0 ? '#fafafa' : '#bbb'},
]}>
<Image style={styles.profile} source={{uri: item.picture}} />
<View style={styles.rightside}>
<Text style={styles.name}>{item.name}</Text>
<Text style={styles.company}>{item.company}</Text>
</View>
</SafeAreaView>
</ScrollView>
)
}}
keyExtractor={item => item._id}
//called search function
ListHeaderComponent={renderHeader()}
/>
</SafeAreaView>
)
}
export default Flatlistexample
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
borderBottomWidth: 1,
borderColor: 'gray',
},
profile: {
width: 50,
height: 50,
borderRadius: 25,
marginLeft: 10,
},
rightside: {
marginLeft: 20,
justifyContent: 'space-between',
marginVertical: 5,
},
name: {
fontSize: 22,
marginBottom: 10,
},
searchContainer: {
padding: 10,
borderWidth: 2,
borderColor: 'gray',
},
textInput: {
fontSize: 16,
backgroundColor: '#f9f9f9',
padding: 10,
},
})
Thanks for your help
Filter Data
onSearchText = (value) => {
this.setState({searchText: value})
if(value.trim() == "" || value == null){
this.setState({list: this.state.list}
} else {
let filter = this.state.list.fillter(data => {
// data fillter logic //
return data;
})
this.setState({filterData: filter})
}
Render FlatList
<FlatList
extradata={this.state}
data={searchText ? filterData : list}
/>
I fixed...
How?
My main data state is constant, i'm filtering on data list with filter state. So my data list doesn't change anytime.
import React, {Component, useState} from 'react'
import {
Text,
StyleSheet,
View,
FlatList,
SafeAreaView,
ScrollView,
Image,
TextInput,
} from 'react-native'
import data from '../../data'
const Flatlistexample = () => {
//main list state
let [list, setList] = useState(data)
//search state
const [search, setSearch] = useState('')
//filter state
const [updated, setUpdated] = useState(data)
//search filter
searchFilter = text => {
// onChangeText
if (text) {
const newData = list.filter(item => {
const listItem = `${item.name.toLowerCase()} ${item.company.toLowerCase()}`
return listItem.indexOf(text.toLowerCase()) > -1
})
setUpdated(newData)
}
//search function
renderHeader = () => {
return (
<View style={styles.seachContainer}>
<TextInput
style={styles.textInput}
placeholder={'Search...'}
value={search}
onChangeText={text => {
searchFilter(text)
setSearch(text)
}}></TextInput>
<Text
style={{
alignItems: 'flex-start',
color: 'black',
fontSize: 22,
}}>
{search}
</Text>
</View>
)
}
return (
<SafeAreaView
style={{
flex: 1,
}}>
<FlatList
//i'm showing filter state
data={updated}
renderItem={({item, index}) => {
return (
<ScrollView>
<SafeAreaView
style={[
styles.container,
{backgroundColor: index % 2 === 0 ? '#fafafa' : '#bbb'},
]}>
<Image style={styles.profile} source={{uri: item.picture}} />
<View style={styles.rightside}>
<Text style={styles.name}>{item.name}</Text>
<Text style={styles.company}>{item.company}</Text>
</View>
</SafeAreaView>
</ScrollView>
)
}}
keyExtractor={item => item._id}
//called search function
ListHeaderComponent={renderHeader()}
/>
</SafeAreaView>
)
}
export default Flatlistexample
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
borderBottomWidth: 1,
borderColor: 'gray',
},
profile: {
width: 50,
height: 50,
borderRadius: 25,
marginLeft: 10,
},
rightside: {
marginLeft: 20,
justifyContent: 'space-between',
marginVertical: 5,
},
name: {
fontSize: 22,
marginBottom: 10,
},
searchContainer: {
padding: 10,
borderWidth: 2,
borderColor: 'gray',
},
textInput: {
fontSize: 16,
backgroundColor: '#f9f9f9',
padding: 10,
},
})
/*
else if(text.length > uzunluk){
setList(data)
const newData = list.filter(item => {
const listItem = `${item.name.toLowerCase()} ${item.company.toLowerCase()}`
return listItem.indexOf(text.toLowerCase()) > -1;
})
setList(newData)
}else if(text.length<uzunluk){
setList(data)
const newData = list.filter(item => {
const listItem = `${item.name.toLowerCase()} ${item.company.toLowerCase()}`
return listItem.indexOf(text.toLowerCase()) > -1;
})
setList(newData)
}
*/

Categories

Resources