React Native - updating UI when in a loop using functional component - reactjs

I am developing a React Native app and I have a process whereby I want to put a progress center or progress bar in the UI as it runs.
I found this code in SO but I'm not sure how to implement in my functional component.
Could please give me an example of how to call ProgressBar from my func component and how to increase progress value.?
Thanks in advance.
const ProgressBar = (props)=>{
const [value] = useState(new Animated.Value(props.value))
useEffect(()=>{
Animated.timing(value, {
toValue: props.value,
duration: 100,
}).start()
}, [props.value])
const width = value.interpolate({
inputRange: [0, 100],
outputRange: ['0%', '100%'],
})
return (
<View style={{
width: '100%',
height: '100%',
flexDirection: 'row',
backgroundColor: 'white',
}}>
<Animated.View style={{
width: width,
height: '100%',
backgroundColor: 'green',
}}></Animated.View>
</View>
)
}

Check a fully working example with progress value change.
import * as React from "react";
import { useEffect, useState } from "react";
import { Text, View, StyleSheet, Animated } from "react-native";
import Slider from "#react-native-community/slider";
import Constants from "expo-constants";
const ProgressBar = (props) => {
const [value] = useState(new Animated.Value(props.value));
useEffect(() => {
Animated.timing(value, {
toValue: props.value,
duration: 100,
}).start();
}, [props.value]);
const width = value.interpolate({
inputRange: [0, 100],
outputRange: ["0%", "100%"],
});
return (
<View
style={{
width: "100%",
height: "100%",
flexDirection: "row",
backgroundColor: "white",
}}
>
<Animated.View
style={{
width: width,
height: "100%",
backgroundColor: "green",
}}
></Animated.View>
</View>
);
};
export default function App() {
const [progress, setProgress] = useState(10);
return (
<View style={styles.container}>
<View style={{ paddingVertical: 20 }}>
<Text> Change slider value to see progress bar follow </Text>{" "}
</View>
<View style={{ height: 20 }}>
{" "}
<ProgressBar value={progress} />{" "}
</View>
<View style={{ paddingVertical: 20 }}>
<Slider
minimumValue={0}
maximumValue={100}
onValueChange={setProgress}
/>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
paddingTop: Constants.statusBarHeight,
backgroundColor: "#ecf0f1",
padding: 8,
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: "bold",
textAlign: "center",
},
});
Expo snack - https://snack.expo.dev/#emmbyiringiro/30efea

Use setter to set the value
const [progress, setProgress] = useState(props.value)
useEffect(()=>{
Animated.timing(value, {
toValue: progress,
duration: 100,
}).start()
}, [progress])
to update progress bar, call setProgress(newValue)

Related

have Request failed with status code 400 error in react native

I am using Axios to get data from JSON files and I tried it in postman it works, also the app works but sometimes when I open the app this error appears: Request failed with status code 400 and data disappears can you help solve. am I fetching data in the wrong way?
if there another way to avoid this error please mention it
here is my code:
`
import { StyleSheet, Text, View, Image, ScrollView, TouchableOpacity, TextInput, Pressable, Dimensions } from 'react-native'
import React, { useEffect, useState } from 'react'
import { useNavigation, useRoute } from "#react-navigation/native";
import axios from 'axios';
import LottieView from 'lottie-react-native';
import { Rating } from 'react-native-stock-star-rating'
import { AntDesign } from '#expo/vector-icons';
const LoadingDirection = () => {
return (
<LottieView
ref={animation => {
animation = animation
}}
style={{
width: 210,
height: 210,
alignSelf: 'center'
}}
source={require('../../assets/gif/loading.json')}
autoPlay
loop
/>
)
}
const ArtistSearch = () => {
const route = useRoute()
let token = route.params.token
const navigation = useNavigation();
const [artist, setArtist] = useState([]);
const [loaded, setLoaded] = useState(false);
const [search, setSearch] = useState('');
const [masterData, setMasterData] = useState([]);
const [empty, SetEmpty] = useState(false)
const ArtistData = async () => {
const resp = await axios.get('https://api.spotify.com/v1/search?query=remaster%2520track%3ADoxy%2520artist%3AMiles%2520Davis&type=artist&market=ES&locale=en-US%2Cen%3Bq%3D0.9&offset=5&limit=10', {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: "Bearer " + token,
},
})
return resp.data.artists.items;
};
useEffect(() => {
ArtistData().then(artists => {
setArtist(artists)
setMasterData(artists)
setLoaded(true);
}).catch(err => {
console.log(err)
});
}, []);
return (
<ScrollView>
<View style={{ alignItems: 'center', marginTop: 20 }}>
<Pressable>
<View style={styles.searchSection}>
<TextInput
style={styles.input}
placeholder="Search for an artist..."
underlineColorAndroid="transparent"
value={search}
/>
<AntDesign name="search1" size={24} color="Black" />
</View>
</Pressable>
</View>
{artist.map((data, i) => (
<TouchableOpacity onPress={() => { navigation.navigate('AlbumScreen',{artistId:data.id,token:token,artistName:data.name}) }} key={i}>
<View>
<View style={styles.paper}>
<Image source={{ uri: data.images.url }} style={{ height: 350, width: Dimensions.get('window').width - 40, resizeMode: 'cover' }} />
<View style={{ height: 1, width: Dimensions.get('window').width - 40, backgroundColor: 'gray', marginBottom: 10 }}></View>
<Text style={{ paddingLeft: 10, fontSize: 24, fontWeight: '600' }}>{data.name}</Text>
<Text style={{ color: 'gray', marginLeft: 10, marginBottom: 10 }}>{data.followers.total} followers</Text>
<View style={{ marginLeft: 10 }}>
<Rating stars={data.popularity / 2} maxStars={5} size={25} />
</View>
<View style={{ marginBottom: 20 }} />
</View>
</View>
</TouchableOpacity>
))}
{!loaded && LoadingDirection()}
</ScrollView>
)
}
export default ArtistSearch
const styles = StyleSheet.create({
paper: {
width: Dimensions.get('window').width - 40,
backgroundColor: 'white',
shadowColor: 'black',
shadowOffset: {
width: 0,
height: 4,
},
shadowOpacity: 0.002,
shadowRadius: 22,
elevation: 3,
margin: 8,
marginTop: 20,
marginLeft: 20,
marginRight: 20,
borderColor: 'gray',
borderWidth: 0.2
},
heading: {
fontSize: 17,
marginBottom: 5,
marginLeft: 10,
marginTop: 10
},
stars: {
display: 'flex',
flexDirection: 'row',
marginLeft: 10, marginBottom: 20
},
starUnselected: {
color: '#aaa',
},
starSelected: {
color: '#ffb300',
},
searchSection: {
width: Dimensions.get('window').width - 40,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
borderColor: 'Black',
borderWidth: 1,
borderRadius: 10,
paddingHorizontal: 10
},
searchIcon: {
padding: 10,
},
input: {
flex: 1,
paddingTop: 10,
paddingRight: 10,
paddingBottom: 10
},
})
`

Attempt to import and use NUMBERPLEASE in React Native Successfully

Below you can find the code created so far. You might see that this code works for a simple web program. But when you attempt to see how it is displayed on MOBILE this error code occurs -> (undefined is not an object (evaluating 'p.Picker.Item')
(Device))
Would anyone possibly have an idea of the reason for this error?
I'm new to REACT NATIVE.
import React, { useState } from 'react';
import {
View,
StyleSheet,
Text,
Animated,
Easing,
Pressable,
TextInput,
} from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import Constants from 'expo-constants';
import {Card} from 'react-native-paper';
import NumberPlease from 'react-native-number-please';
import { useHeaderHeight } from '#react-navigation/elements';
const OrderPizza = () => {
const initialValues = [{ id: "pizza", value: 3 }];
const [pizzas, setPizzas] = useState(initialValues);
const pizzaNumbers = [{ id: "pizza", label: "🍕", min: 0, max: 99 }];
return (
<View>
<Text>I would like</Text>
<NumberPlease
digits={pizzaNumbers}
values={pizzas}
onChange={(values) => setPizzas(values)}
/>
</View>
);
};
export default function DosingCalculator({ navigation }) {
const headerHeight = useHeaderHeight();
const topMargin = headerHeight + 'px 0 0 0';
const animatedValue = React.useRef(new Animated.Value(0)).current;
const startAnimation = (toValue) => {
Animated.timing(animatedValue, {
toValue,
duration: 400,
easing: Easing.linear,
useNativeDriver: false,
}).start();
};
const left = animatedValue.interpolate({
inputRange: [0, 1],
outputRange: ['2%', '50%'],
extrapolate: 'clamp',
});
const scale = animatedValue.interpolate({
inputRange: [0, 0.5, 1],
outputRange: [1, 0.9, 1],
extrapolate: 'clamp',
});
return (
<LinearGradient colors={['#20c1c1', '#8dc642']} style={styles.gradient}>
<View style={styles.mainContainer}>
<View style={styles.container}>
<Text>
Secondary Readings
<View style={styles.sliderContainer}>
<Animated.View style={[styles.slider, { left }]} />
<Pressable
style={styles.clickableArea}
onPress={startAnimation.bind(null, 0)}>
<Animated.Text
style={[styles.sliderText, { transform: [{ scale }] }]}>
Show
</Animated.Text>
</Pressable>
<Pressable
style={styles.clickableArea}
onPress={startAnimation.bind(null, 1)}>
<Animated.Text
style={[styles.sliderText, { transform: [{ scale }] }]}>
Hide
</Animated.Text>
</Pressable>
</View>
</Text>
<View
style={{
flex: 1,
alignContent: 'center',
justifyContent: 'center',
padding: 12,
}}>
<Text>Pool Volume</Text>
<TextInput
style={{
borderRadius: 10,
padding: 8,
backgroundColor: '#f5f5f5',
}}
onChangeText={(text) => setGallons(text)}
/>
</View>
</View>
<View style={styles.container}>
<Text>Current</Text>
<OrderPizza/>
</View>
<View style={styles.container}>
<Text>Desired</Text>
</View>
</View>
</LinearGradient>
);
}
const styles = StyleSheet.create({
container: {
width: '100%',
alignItems: 'center',
justifyContent: 'center',
textAlign: 'center',
margin: 30,
flexDirection: 'row',
},
gradient: {
flex: 1,
paddingLeft: 15,
paddingRight: 15,
},
sliderContainer: {
width: '75%',
height: 50,
borderRadius: 10,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
backgroundColor: '#e0e0e0',
},
mainContainer: {
width: '100%',
margin: 8,
borderRadius: 10,
alignItems: 'center',
backgroundColor: 'white',
},
clickableArea: {
width: '50%',
height: '100%',
justifyContent: 'center',
alignItems: 'center',
},
sliderText: {
fontSize: 17,
fontWeight: '500',
},
slider: {
position: 'absolute',
width: '48%',
height: '90%',
borderRadius: 10,
backgroundColor: '#20c1c1',
},
});

Navigating to another screen while passing state to a button

So I originally needed to pass states while navigating from a screen to another because I thought that would be enough to update a button as well as the screen iteself. However, the button that controlled the states is not being updated with the screen.
In the demo provided below(I included the code here as well) you can see that when navigating from Screen3, the state updates so that the red screen renders but the button at the top does not update as well.
How can I update the button along with the screen being updated?
I need to go from screen3 to the red screen while the button at the top shows we are on the red screen as well.
Here is the demo as well as the code below. Please keep in mind you must run the snack on IOS or android and you need to be running Expo Version 42(located in the bottom right of the screen)
Thank you for any insight at all! I appreciate it more than you know.
Home.js
import Slider from './components/slider'
const Home = ({ route }) => {
const [isVisile, setIsVisible] = React.useState(true);
const [whichComponentToShow, setComponentToShow] = React.useState("Screen1");
React.useEffect(() => {
if(route.params && route.params.componentToShow) {
setComponentToShow(route.params.componentToShow);
}
}, [route.params]);
const goToMap = () => {
setComponentToShow("Screen2");
}
const goToList = () => {
setComponentToShow("Screen1");
}
return(
<View style={{backgroundColor: '#d1cfcf' ,flex: 1}}>
{whichComponentToShow === 'Screen1' && <ListHome />}
{whichComponentToShow === 'Screen2' && <MapHome />}
<View style={{position: 'absolute', top: 0, left: 0, right: 1}}>
<Slider
renderMap={goToMap}
renderList={goToList}
/>
</View>
</View>
);
}
Screen3.js
const Screen3 = (props) => {
const navigation = useNavigation();
const onPress = () => {
navigation.navigate('Home', {
screen: 'Home',
params: {
componentToShow: 'Screen2'
}
});
}
return (
<View
style={{
flex: 1,
backgroundColor: 'white',
justifyContent: 'center',
alignItems: 'center',
}}>
<TouchableOpacity onPress={onPress}>
<Text style={{ color: 'black', fontSize: 25 }}>
Navigate to home and change to map screen
</Text>
</TouchableOpacity>
</View>
);
};
Finally Slider.js
const Slider = (props) => {
const [active, setActive] = useState(false)
let transformX = useRef(new Animated.Value(0)).current;
useEffect(() => {
if (active) {
Animated.timing(transformX, {
toValue: 1,
duration: 300,
useNativeDriver: true
}).start()
} else {
Animated.timing(transformX, {
toValue: 0,
duration: 300,
useNativeDriver: true
}).start()
}
}, [active]);
const rotationX = transformX.interpolate({
inputRange: [0, 1],
outputRange: [2, Dimensions.get('screen').width / 4]
})
return (
code for animation
)
Your Slider component needs to listen to screen focus with useFocusEffect and react accordingly. I added new props active to detect if the map screen is active.
Slider.js
import * as React from 'react';
import { useState, useEffect, useRef } from 'react'
import { View, Text, StyleSheet, Animated, TouchableOpacity, SafeAreaView, Dimensions, } from 'react-native';
import {
scale,
verticalScale,
moderateScale,
ScaledSheet,
} from 'react-native-size-matters';
import { useFocusEffect } from '#react-navigation/native';
const Slider = (props) => {
const [active, setActive] = useState(false)
let transformX = useRef(new Animated.Value(0)).current;
useFocusEffect( React.useCallback(()=>{
setActive(Boolean(props.active))
console.log()
},[props.active]))
useEffect(() => {
if (active) {
Animated.timing(transformX, {
toValue: 1,
duration: 300,
useNativeDriver: true
}).start()
} else {
Animated.timing(transformX, {
toValue: 0,
duration: 300,
useNativeDriver: true
}).start()
}
}, [active]);
const rotationX = transformX.interpolate({
inputRange: [0, 1],
outputRange: [2, Dimensions.get('screen').width / 4]
})
return (
<SafeAreaView style={{
alignItems: 'center',
backgroundColor:'transparent'
}}>
<View style={{
flexDirection: 'row',
position: 'relative',
height: 45,
width: 240,
borderRadius: 10,
backgroundColor: 'white',
marginHorizontal: 5
}}>
<Animated.View
style={{
position: 'absolute',
height: 45 - 2*2,
top: 2,
bottom: 2,
borderRadius: 10,
width: Dimensions
.get('screen').width / 3 - 3.5 ,
transform: [
{
translateX: rotationX
}
],
backgroundColor: '#d1cfcf',
}}
>
</Animated.View>
<TouchableOpacity style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}} onPress={() => {setActive(false); props.renderList() }}>
<Text>
List
</Text>
</TouchableOpacity>
<TouchableOpacity style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}} onPress={() => {setActive(true); props.renderMap() }}>
<Text>
Map
</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
);
}
export default Slider
I update Slider Component in Home.js as below.
<Slider
renderMap={goToMap}
renderList={goToList}
active={route.params && route.params.componentToShow==='Screen2'}
/>
Check full working snack:
https://snack.expo.dev/#emmbyiringiro/283f93

How to move down a object using button in react native?

Actually I want to do something like that (Image attached):
There have a box, and two buttons. If I press button 1 then the box moved left. And if I press button 2 then the box moved right.
I want, when the box move right and overcome the bar 1 then the box moved down on the bar 2.
But I have no idea how to do it.
Here is my code:
import React, {Component} from 'react';
import {
View,
Text,
StyleSheet,
Animated,
TouchableOpacity,
ScrollView,
Image,
} from 'react-native';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
left: 20,
};
}
moveRight = () => {
this.setState({left: this.state.left + 10}); // 10 is value of change.
};
moveLeft = () => {
this.setState({left: this.state.left - 10}); // 10 is value of change.
};
render() {
return (
<View style={styles.container}>
<Image
style={{left: this.state.left, height: 120, width: 120}}
source={require('./assets/box.png')}
/>
<Image
style={{height: 20, width: 180, marginTop: -12, marginLeft: 25}}
source={require('./assets/log.png')}
/>
<Image
style={{height: 20, width: 200, marginTop: 150, marginLeft: 185}}
source={require('./assets/log.png')}
/>
<View style={styles.buttonsContainer}>
<TouchableOpacity onPress={this.moveLeft}>
<Image
style={{height: 60, width: 60}}
source={require('./assets/left-button.png')}
/>
</TouchableOpacity>
<TouchableOpacity onPress={this.moveRight}>
<Image
style={{height: 60, width: 60}}
source={require('./assets/right-button.png')}
/>
</TouchableOpacity>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
textCenter: {
alignSelf: 'center',
textAlign: 'center',
},
levelHeading: {
fontWeight: 'bold',
fontSize: 35,
color: '#CC8A4F',
},
buttonsContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
marginTop: 200,
paddingLeft: 80,
paddingRight: 80,
},
});
Please help me!
Thanks!
import React, { useEffect } from "react";
import { Animated, Text, View, StyleSheet, Button } from "react-native";
const App = () => {
const moveAnimation = new Animated.ValueXY({ x: 10, y: 450 });
useEffect(() => {
moveAnimation;
}, []);
const _moveBallLeft = () => {
Animated.spring(moveAnimation, {
toValue: { x: 250, y: 450 },
}).start();
};
const _moveBallRight = () => {
Animated.spring(moveAnimation, {
toValue: { x: 10, y: 450 },
}).start();
};
return (
<View style={styles.container}>
<Animated.View style={[styles.tennisBall, moveAnimation.getLayout()]}>
<View style={styles.button}>
<Text style={styles.buttonText}>ball</Text>
</View>
</Animated.View>
<View
style={{
flexDirection: "row-reverse",
justifyContent: "space-evenly",
}}
>
<View style={{ alignSelf: "center" }}>
<Button title=">" onPress={_moveBallLeft}></Button>
</View>
<View style={{ alignSelf: "center", marginLeft: "2%" }}>
<Button title="<" onPress={_moveBallRight}></Button>
</View>
</View>
</View>
);
};
export default App;
const styles = StyleSheet.create({
container: {
flex: 2,
backgroundColor: "#ecf0f1",
},
tennisBall: {
display: "flex",
justifyContent: "center",
alignItems: "center",
backgroundColor: "greenyellow",
borderRadius: 100,
width: 100,
height: 100,
},
button: {
paddingTop: 24,
paddingBottom: 24,
},
buttonText: {
fontSize: 24,
color: "#333",
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

React Native (android) , components overlapping with shadow issue

I am using a custom component with image and text. The image is relative to the text. Please see the screenshot.
image 1
image 2.
I have used the TouchableOpacity component as root view for that.
In screenshots when long press on the component, two views are overlapping with shadow. It looks ugly when long press.
Please see the code below for reusable component.
'use strict';
import React, {Component} from 'react';
import {
StyleSheet,
Text,
View,
TouchableOpacity,
Image,
} from 'react-native';
export default class ExampleButton extends Component {
constructor (props) {
super (props);
}
_handleOnPress = () => {
console.log('pressed!!!');
};
render () {
console.log (this.props);
return (
<TouchableOpacity
onPress={this.handleOnPress}
>
<View style={styles.btnCompContainer}>
<View
style={{
backgroundColor: '#FFF',
justifyContent: 'center',
borderRadius: 30,
height: 50,
width: '100%',
}}
>
<Text style={styles.btnTxt}>{this.props.buttonText}</Text>
</View>
<View style={[styles.btnElmContainer]}>
<Image
style={[{height: 30, width: 30,resizeMode:'stretch'}]}
source={this.props.image}
/>
</View>
</View>
</TouchableOpacity>
);
}
}
const styles = StyleSheet.create ({
btnCompContainer: {
flexDirection: 'row',
alignItems: 'center',
height: 60,
marginLeft: 10,
marginRight: 20,
},
btnElmContainer: {
position: 'absolute',
justifyContent: 'center',
alignItems: 'center',
width: 60,
height: 60,
backgroundColor:'#fff',
borderRadius: 30,
shadowColor: '#000000',
shadowOffset: {
width: 1,
height: 1,
},
elevation:5,
shadowRadius: 2,
shadowOpacity: 0.3,
},
btnTxt: {
marginLeft: 80,
color: '#9e9e9e',
fontSize: 16,
fontWeight: 'bold',
textAlign: 'left',
},
});
Here I am using this reusable component in code.
'use strict';
import React, {Component} from 'react';
import {
Animated,
StyleSheet,
Text,
TextInput,
View,
Image,
ImageBackground,
TouchableOpacity,
Button,
StatusBar,
Easing
} from 'react-native';
// Custom Components
const searchBGImg = require('../assets/search-bg-kit.png');
const houseLogo = require('../Resources/house.png');
import ExampleButton from './components/common/example-button';
export default class TypeSelect extends Component<Props> {
// Navigation Option
static navigationOptions = {
header: null
}
constructor() {
super();
this.state = {
visible: false,
x: new Animated.Value(-100),
};
}
slide = () => {
Animated.spring(this.state.x, {
toValue: 0,
easing: Easing.easeOutBack
}).start();
this.setState({
visible: true,
});
};
gotoSearch = () =>{
this.props.navigation.navigate('DocSearch')
}
componentDidMount(){
this.slide();
}
render() {
return (
<View style={styles.container}>
<ImageBackground source={searchBGImg} style={styles.imgBG}>
<View style={{alignItems:'center', marginBottom:20}}>
<Image style={{height:57, width:69, marginBottom:12}} source={houseLogo} />
</View>
<View>
<Animated.View
style={[styles.slideView, {
transform: [
{
translateX: this.state.x
}
]
}]}>
<ExampleButton image={houseLogo} buttonText={'Click here'} />
<ExampleButton image={houseLogo} buttonText={'Click here'} />
</Animated.View>
</View>
</ImageBackground>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
imgBG:{
flex: 1,
flexDirection: "column",
justifyContent:"center",
width: "100%",
height: "100%"
}
})
It is working fine in iOS, but it's not working in android up to the mark. Please help me to work it in android.
Thanks in advance.
You should use renderToHardwareTextureAndroid prop on <View /> component.
In your example like this:
<View style={styles.btnCompContainer} renderToHardwareTextureAndroid >
<View
style={{
backgroundColor: '#FFF',
justifyContent: 'center',
borderRadius: 30,
height: 50,
width: '100%',
}}
>
<Text style={styles.btnTxt}>{this.props.buttonText}</Text>
</View>
<View style={[styles.btnElmContainer]}>
<Image
style={[{height: 30, width: 30,resizeMode:'stretch'}]}
source={this.props.image}
/>
</View>
</View>

Resources