Current Output:
Expected Output:
Current Code Implementation:
import React from 'react'
import { LineChart, XAxis, YAxis } from 'react-native-svg-charts'
import { View, Text } from 'react-native'
import { Line, Circle, G, Rect, } from 'react-native-svg'
export default class Chart extends React.PureComponent {
handleFill = (value) => {
if (value>100){
return "rgba(190, 30, 45, 0.5)"
}
else if (value>80 && value<=100){
return "yellow"
}
else{
return "#CCE6D0"
}
}
render() {
const data = [
...
];
const values = data.map(a => a.value);
const days = data.map(a => a.day);
const axesSvg = { fontSize: 10, fill: 'grey' };
const verticalContentInset = { top: 10, bottom: 10 }
const xAxisHeight = 30
const Decorator = ({x, y, data}) => {
return values.map((value, index) => (
<View>
<View style={{marginBottom:50}}>
<Rect
x={x(index)-1.75}
y={y(value+8)}
width="4"
height="40"
fill={this.handleFill(value)}
/>
</View>
<Circle
key={index}
cx={x(index)}
cy={y(value)}
r={2}
stroke={'#639123'}
fill={'#606060'}
/>
</View>
));
};
return (
<View>
<Text style={{fontSize:10}}>BPM</Text>
<View style={{ height: 200, flexDirection: 'row' }}>
<YAxis
...
/>
<View style={{ flex: 1, marginLeft: 10 }}>
<LineChart
...
>
<Decorator />
</LineChart>
<XAxis
....
/>
</View>
</View>
</View>
)
}
}
I am using the react-native-svg-charts library to render a line chart with custom handlers.
As seen in the code, the handler consists of a circle and a rect, which simply do not show up. Could this be a library version problem? I have updated both react-native-svg and react-native-svg-charts to the latest version. What am I missing? Any ideas?
I've gotten it to work like this:
import React from 'react';
import {LineChart, XAxis, YAxis} from 'react-native-svg-charts';
import {View, Text} from 'react-native';
import {Svg, Line, Circle, G, Rect} from 'react-native-svg';
export default class CustomLineChartOne extends React.PureComponent {
handleFill = (value) => {
if (value > 100) {
return 'rgba(190, 30, 45, 0.5)';
} else if (value > 80 && value <= 100) {
return 'yellow';
} else {
return '#CCE6D0';
}
};
render() {
const xAxisLabels = [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec',
];
const data = [50, 10, 40, 95, -4, -24, 85, 91, 35, 53, -53, 24];
const Decorator = ({x, y, data}) => {
return data.map((value, index) => (
<View>
<Rect
x={x(index) - 1.75}
y={y(value + 8)}
width="4"
height="40"
rx="2"
fill={this.handleFill(value)}
/>
<Circle
key={index}
cx={x(index)}
cy={y(value)}
r={2}
stroke={'#639123'}
fill={'#606060'}
/>
</View>
));
};
return (
<View
style={{
height: 200,
flexDirection: 'row',
padding: 20,
}}>
<YAxis
data={data}
contentInset={{top: 20, bottom: 20}}
svg={{
fill: 'black',
fontSize: 10,
}}
/>
<View style={{flex: 1}}>
<LineChart
style={{flex: 1}}
data={data}
svg={{stroke: 'rgb(134, 65, 244)'}}
contentInset={{top: 10, bottom: 10, left: 10, right: 10}}>
<Decorator />
</LineChart>
<XAxis
style={{marginHorizontal: -10}}
data={data}
formatLabel={(value, index) => xAxisLabels[index]}
contentInset={{left: 10, right: 10}}
svg={{fontSize: 10, fill: 'black'}}
/>
</View>
</View>
);
}
}
The important parts to look at here are how the data and xAxisLabels are defined, how the labels are formatted and how data is mapped over inside the decorator to create the bars and circles.
It's not entirely clear what the exact problem was with your code as you've left out some important parts, but I think the problem was mainly related to how you had set up your data.
The result looks like this:
Related
after recording a 7-second video, I save it and then store it on my server.
however, when playing the video back it has no video, only audio.
video link: https://storage.googleapis.com/clipdrop-prod/tfZJe6V5ImfAYD_k9GMnKK6JD.mp4?avoidCache=1
here is the media info of said video
below is my code
once the component loads, it calls startRecording function. which starts the recording and waits for the recording to be "stopped" (aka saved), which it then loads the uri for the local file it has saved to on the device from videoData.
Code
import react, { useRef, useState, useEffect } from 'react';
import { Text, View, Image } from 'react-native';
import PrimaryButton from '../../../components/buttons/PrimaryButton';
import { windowWidth } from '../../../helpers/screenHelper';
import { Camera, CameraRecordingOptions, CameraType, requestCameraPermissionsAsync, requestMicrophonePermissionsAsync, VideoCodec } from 'expo-camera';
import CountDown from './CountDown';
import { CountDownStyles } from './CountDown.styles';
export default function RecordAnswerView(props:any){
const { question, onComplete, onRestart } = props;
const [showCountDown, setShowCountDown] = useState(true);
const [countDownText, setCountDownText] = useState(3);
const cameraRef = useRef<any>(null);
const [showRedFlash, setShowRedFlash] = useState(false);
const [permission, requestPermission] = Camera.useCameraPermissions();
const [videoData, setVideoData] = useState(true);
let answerCounterState:any = null;
const saveRecording = () => { cameraRef.current.stopRecording();}
const restartRecording = () => {onRestart();}
const startRecording = async () =>{
let videoData = await cameraRef.current.recordAsync({
codec: VideoCodec.H264,
quality: "720p",
videoBitrate: 5*1000*1000
});
console.log(videoData);
onComplete((videoData as any).uri);
};
const startCountDown = () => {
setCountDownText(3);
setShowCountDown(true);
setTimeout(()=>{
setCountDownText(3);
setTimeout(()=>{
setCountDownText(2);
setTimeout(()=>{
setCountDownText(1);
setTimeout(async ()=>{
setShowCountDown(false);
setCountDownText(3);
await startRecording();
}, 1000);
}, 1000);
}, 1000);
}, 1000);
}
useEffect(()=>{
async function init(){
let audio = await requestMicrophonePermissionsAsync();
let camera = await requestCameraPermissionsAsync();
setShowRedFlash(false);
startCountDown();
}
init();
}, []);
return <>
<View style={{marginHorizontal:12}}>
<Text style={{textAlign:'center', fontSize:22, marginVertical:12}}>Answer Recorder</Text>
<Camera ref={cameraRef} type={CameraType.front} style={{width: windowWidth - 20, height: (windowWidth - 20) * 1.02}}>
<View style={{width:"100%", height:"100%", alignItems:'center', justifyContent:'center'}}>
<Text style={{display: showCountDown ? 'flex' : 'none', fontSize:32, backgroundColor:'#4A86E8', color:"#FFFFFF" ,paddingVertical: 2, paddingHorizontal: 14, borderRadius: 16}}>{ countDownText }</Text>
</View>
</Camera>
<View style={{alignItems:'center', justifyContent:'center', flexDirection:'row', alignContent:'center', marginTop: 5}}>
<Text style={{borderTopLeftRadius: 8, borderBottomLeftRadius: 8, textAlign:'center', color:'#E9E9E9',backgroundColor:'#333333', width: windowWidth / 2, padding: 8, fontSize:13, marginLeft: 4, paddingVertical:9}}>Recommended Answer Time</Text>
{ (!showCountDown) ? <CountDown totalTime={question.recommend_answer_duration} onZero={()=>{
saveRecording();
setShowRedFlash(false);
setShowCountDown(false);
}}
onFlip={()=>{
setShowRedFlash(!showRedFlash);
}}/> : <Text style={ CountDownStyles.textStyle }>{question.recommend_answer_duration} Seconds Remaining</Text> }
</View>
{ !showCountDown && <><PrimaryButton onPress={()=>{saveRecording();}} text={"Save"} containerStyle={{ marginTop: 20, marginBottom: 8, width: windowWidth - 20}} fontSize={20}/>
<PrimaryButton onPress={()=>{restartRecording();}} text={"Restart Recording"} containerStyle={{marginTop: 5, marginBottom: 10, width: windowWidth - 20}} fontSize={10} height={32}/>
</>}
</View>
<View style={{display: showRedFlash ? "flex" : "none", position:'absolute', top:0, bottom: 0, left: 0, right: 0, backgroundColor: '#ff000036'}} pointerEvents={"none"}>
</View>
</>
}
Testing
Test on a physical android device with the last Android OS
I am a beginner with React Native, so I need help with following:
I am programming an App, where you can choose between two radio button groups. To every radio button should belong data (key and value pairs, in categories). If choose two options and afterwards press the butto "Create my plan" it should randomly choose some entries of the key value kategories and create a flatlist from it.
My problem is, that I dont know how I can pass data bewteen two classes or if there is an other way to realize what I picture.
Please do not be put off by the amount of code, if you copy it and paste it into an empty project, it works immediately and you will understand my question.
I am very grateful for your help.
Here is my Code:
import React, { Component, useState, createContext } from 'react';
import { StyleSheet, FlatList, Text, Dimensions, Button, View, Image, ScrollView, TouchableOpacity, Animated } from 'react-native';
import { registerRootComponent } from 'expo';
import { RadioButton } from 'react-native-paper';
import 'react-native-gesture-handler';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
//Ein StackNavigator-Objekt wird erzeugt
const Stack = createStackNavigator();
class Auswahl extends React.Component {
state = {
value1: 'first',
value2: 'first',
value3: 'first',
checked: 'agnostic'
};
render() {
return (
<View style={{alignItems:"center", flex:1, flexDirection:'column' }}>
<View style={{position:'absolute', alignItems:"center", flex:1, flexDirection:'column'}}>
<Text style={{ marginTop:50, marginBottom:10 }}>Auf welchem Niveau praktizierst du?</Text>
<View style={{flex: 1, flexDirection: 'column', marginBottom: 20}}>
<RadioButton.Group
onValueChange={value1 => this.setState({ value1 })}
value={this.state.value1}>
<Text>Anfgänger</Text>
<RadioButton.Android value="first" />
<Text>Geübt</Text>
<RadioButton.Android value="second" />
<Text>Eingeschränkt</Text>
<RadioButton.Android value="third" />
</RadioButton.Group>
<Text style={{ marginBottom: 10 }}>Möchtest du einen Fokus setzten?</Text>
<RadioButton.Group
onValueChange={value2 => this.setState({ value2 })}
value={this.state.value2}>
<Text>Dehnung</Text>
<RadioButton.Android value="first" />
<Text>Hüftöfner</Text>
<RadioButton.Android value="second" />
<Text>Energie</Text>
<RadioButton.Android value="third" />
</RadioButton.Group>
<Button style={{margin:10, padding:10}} title="Erstelle meinen Plan" onPress={() =>
this.props.navigation.navigate('UebungenAnzeigen') }/>
</View>
<View/>
</View>
</View>
);
}
}
class UebungenAnzeigen extends React.Component {
constructor(props){
super(props);
this.state = {
data:[
{
"name": "Herabschauender Hund",
"kategorie":"Basic",
"nummer" : "0",
"erklaerung": "Steißbein zur Decke | Rücken gerade | Kopf in Verlängerung der Wirbelsäule",
"photo": "",
"dauer": 30
},
{
"name": "Katze",
"nummer" : "2",
"erklaerung": "Steißbein zur Decke | Rücken gerade | Kopf in Verlängerung der Wirbelsäule",
"photo": "",
"dauer": 20
},
]
}
}
render() {
function Item({ item }) {
const [shouldShow, setShouldShow] = useState(true);
return (
<View style={styles.container}>
{shouldShow ? (
null
) :
<View style={stylesUebungAnzeigen.uebung}>
<Text>Details</Text>
<Text style={{marginTop: 20 }}>{item.name}</Text>
<TouchableOpacity style={{marginTop: 100, color:'green'}} onPress= {() => setShouldShow(!shouldShow)}>Zurück zur Übersicht</TouchableOpacity>
</View>
}
<View style={stylesUebungAnzeigen.listItem}>
<Image source={item.photo} style={{width:90, height:60, borderRadius:10}} />
<View style={{alignItems:"center",flex:1}}>
<Text style={{fontWeight:"bold"}}>{item.name}</Text>
<Text>{item.dauer}</Text>
</View>
<TouchableOpacity onPress={() => setShouldShow(!shouldShow)} style={{height:50,width:50,
justifyContent:"center", alignItems:"center"} }>
<Text style={{color:"green", fontWeight:"bold"}}>Hilfestellung?</Text>
</TouchableOpacity>
</View>
</View>
);
}
return (
<View>
<View style={stylesUebungAnzeigen.container2}>
<FlatList style={{flex:1}}
data={this.state.data}
renderItem={({ item }) => <Item item= {item}/>}
keyExtractor={item => item}
/>
</View>
</View>
);
}
}
const stylesUebungAnzeigen = StyleSheet.create ({
buttons: {
flex: 1,
alignSelf:"center",
height: 10,
width: 30
},
uebung:{
fex:1,
alignSelf:"center",
justifyContent:"center",
height: 911,
width: 318,
borderColor:'grey',
backgroundColor: 'white'
},
text:{
flex:1,
justifyContent: 'center'
},
container2: {
flex: 1,
backgroundColor: '#F7F7F7',
marginTop:60
},
title: {
fontSize: 14,
backgroundColor: '#FFF',
marginTop: 10
},
listItem:{
margin:10,
padding:10,
backgroundColor:"#FFF",
width:"80%",
flex:1,
alignSelf:"center",
flexDirection:"row",
borderRadius:2
},
});
// geht nicht umzubennen nochmal gucken
const styles = StyleSheet.create({
item: {
backgroundColor: '#f9c2ff',
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
},
container:{
flex: 1,
marginTop: 20,
},
group: {
flexDirection: 'row',
justifyContent: 'space-around',
},
SeparatorLine :{
backgroundColor : '#fff',
width: 1,
height: 40
},
elementsContainer: {
backgroundColor: '#ecf5fd',
}
});
export default class Willkommen extends Component {
render() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Auswahl"
component={Auswahl}
/>
<Stack.Screen
name="UebungenAnzeigen"
component={UebungenAnzeigen}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
}
registerRootComponent(Willkommen);
I don't completely understand the question. Because its just if else to check which one is selected (according to your schema).
How you will pass values from one screen to another is as follows.
<Button style={{margin:10, padding:10}} title="Erstelle meinen Plan" onPress={() =>
this.props.navigation.navigate('UebungenAnzeigen',{
data : {value1, value2 ,...etc}}) }/>
And on next screen you can receive that data using following code.
let data = props.route.params?.data;
console.log(data.value1, data.value2)
Background:
I am trying to add a tooltip to a react-native-svg chart following this tutorial.
The link to the tutorial: Link
Current Code Implementation:
import React, {useState} from 'react';
import {View, Text, Dimensions} from 'react-native';
import {LineChart} from 'react-native-chart-kit';
import {Rect, Text as TextSVG, Svg} from 'react-native-svg';
const Charts = () => {
let [tooltipPos, setTooltipPos] = useState({
x: 0,
y: 0,
visible: false,
value: 0,
});
return (
<View>
<LineChart
data={{
labels: ['January', 'February', 'March', 'April', 'May', 'June'],
datasets: [
{
data: [100, 110, 90, 130, 80, 103],
},
],
}}
width={Dimensions.get('window').width}
height={250}
yAxisLabel="$"
yAxisSuffix="k"
yAxisInterval={1}
chartConfig={{
backgroundColor: 'white',
backgroundGradientFrom: '#fbfbfb',
backgroundGradientTo: '#fbfbfb',
decimalPlaces: 2,
color: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
labelColor: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
style: {
borderRadius: 0,
},
propsForDots: {
r: '6',
strokeWidth: '0',
stroke: '#fbfbfb',
},
}}
bezier
style={{
marginVertical: 8,
borderRadius: 6,
}}
decorator={() => {
return tooltipPos.visible ? (
<View>
<Svg>
<Rect
x={tooltipPos.x - 15}
y={tooltipPos.y + 10}
width="40"
height="30"
fill="black"
/>
<MaterialCommunityIcons
name="run"
size={32}
color="rgb(67, 67, 67)"
/>
<TextSVG
x={tooltipPos.x + 5}
y={tooltipPos.y + 30}
fill="white"
fontSize="16"
fontWeight="bold"
textAnchor="middle">
{tooltipPos.value}
</TextSVG>
</Svg>
</View>
) : null;
}}
onDataPointClick={(data) => {
let isSamePoint = tooltipPos.x === data.x && tooltipPos.y === data.y;
isSamePoint
? setTooltipPos((previousState) => {
return {
...previousState,
value: data.value,
visible: !previousState.visible,
};
})
: setTooltipPos({
x: data.x,
value: data.value,
y: data.y,
visible: true,
});
}}
/>
</View>
);
};
Question:
I want to add the icon(Running icon) as seen on the image above, to be next to the tool-tip text.
The Icon, then the text inside the rectangle filled in Black. When I try to position it,, it shows up on the extreme top left for some reason. How do I position it?
You can use the ForeignObject component from react-native-svg and change your decorator to something like this:
decorator={() => {
return tooltipPos.visible ? (
<ForeignObject x={tooltipPos.x} y={tooltipPos.y}>
<View
style={{
width: 70,
flexDirection: 'row',
backgroundColor: 'black',
}}>
<MaterialCommunityIcons
name="run"
size={32}
color="rgb(67, 67, 67)"
/>
<Text
style={{
color: 'white',
fontSize: 16,
fontWeight: 'bold',
textAnchor: 'middle',
}}>
{tooltipPos.value}
</Text>
</View>
</ForeignObject>
) : null;
}}
The problem with what you had before is that the react-native-svg Text and Rect components use x and y coordinates and your icon doesn't, so the positioning will be off.
The benefit of the approach shown above is that you only have to specify the x and y props of the ForeignObject. Everything inside the ForeignObject can be regular views, positioned as you normally would (https://github.com/react-native-community/react-native-svg#foreignobject).
I've chosen the tooltipPos.x and tooltipPos.y for the x and y prop values of the ForeignObject respectively, but you could add an offset if necessary.
Be sure to import ForeignObject from react-native-svg.
I know there are several questions with this issue but mine is different.
I trying to display an image in my Flatlist card that is coming from an API. However it is not showing up.
BUT...when I display this image in another part of my code (in an Autocomplete list) using the same code basically, it works. Also, when I try an url from an image on the Web, it displays inside the flatlist correctly
Here's my Flatlist code:
<FlatList
data={this.state.myGamesArray}
renderItem={({ item }) => (
<Card>
<CardItem>
<View>
<Image
style={styles.gameImage}
source={{uri: item.background_image}}
/>
</View>
</CardItem>
<CardItem>
<View>
<Text style={styles.usergameText}>
{item}
</Text>
</View>
</CardItem>
</Card>
)}
keyExtractor={(item,index) => index.toString()}
/>
Here is my Autocomplete code in which I use the same image bracket-thingy
<View style={styles.iconContainer} >
<TouchableOpacity onPress={() => this.setState({ query: item.name})}
style={styles.autocompleteList} >
<View>
<Image
style={styles.gameImage}
source={{uri: item.background_image}}
/>
</View>
<Text style={styles.gameText}>
{item.name}
</Text>
</TouchableOpacity>
</View>
I ran console.item(item.background_image) both inside the Flatlist(first snippet) and the Autocomplete list (Second snippet). The first shows 'undefined' and the second it shows all the URIs
App.js full code:
/*This is an example of AutoComplete Input/ AutoSuggestion Input*/
import React, { Component } from 'react';
//import react in our code.
import { StyleSheet, Text, TouchableOpacity, View, Image, FlatList, Alert, TouchableWithoutFeedback, Keyboard } from 'react-native';
//import all the components we are going to use.
import Autocomplete from 'react-native-autocomplete-input';
import { Button, List, Container, ListItem, Card, CardItem, Header, Item } from 'native-base';
import { Entypo } from '#expo/vector-icons'
//import Autocomplete component
//const API = 'https://api.rawg.io/api/games?page=1';
//Demo base API to get the data for the Autocomplete suggestion
class App extends Component {
constructor(props) {
super(props);
//Initialization of state
//films will contain the array of suggestion
//query will have the input from the autocomplete input
this.state = {
myGamesArray: [],
games: [],
query: ' ',
};
}
componentDidMount() {
//First method to be called after components mount
//fetch the data from the server for the suggestion
fetch('https://api.rawg.io/api/games?page=1&platforms=18', {
"method": "GET",
"headers": {
"x-rapidapi-host": "rawg-video-games-database.p.rapidapi.com",
"x-rapidapi-key": "495a18eab9msh50938d62f12fc40p1a3b83jsnac8ffeb4469f"
}
})
.then(res => res.json())
.then(json => {
const { results: games } = json;
this.setState({ games });
//setting the data in the games state
});
}
findGame(query) {
let i;
//method called everytime when we change the value of the input
if (query === '') {
//if the query is null then return blank
return [];
}
const { games } = this.state;
//making a case insensitive regular expression to get similar value from the film json
const regex = new RegExp(`${query.trim()}`, 'i');
//return the filtered game array according the query from the input
return games.filter(game => game.name.search(regex) >= 0);
}
AddItemsToArray = () => {
var i
//verifica se input esta vazio
if (this.state.query === '') {
return Alert.alert('Voce não selecionou um jogo')
}
//VERIFY IF GAME IS IN THE ARRAY
for (i = 0; i < this.state.games.length - 1; i++) {
if (this.state.query !== this.state.games[i].name) {
if (i === this.state.games.length - 2) {
return Alert.alert('Este jogo nao existe')
}
else {
continue
}
} else {
break
}
}
//verifica repetido
if (this.state.myGamesArray.includes(this.state.query)) {
return Alert.alert('Este jogo já foi adicionado')
}
else {
//Adding Items To Array.
this.setState(prevState => {
const { myGamesArray, query } = prevState;
return {
myGamesArray: [...myGamesArray, query.toString()],
};
},
// Use setState callback to alert with the updated state
);
}
}
render() {
const { query } = this.state;
const games = this.findGame(query);
const comp = (a, b) => a.toLowerCase().trim() === b.toLowerCase().trim();
return (
<TouchableWithoutFeedback
onPress={() => {
Keyboard.dismiss()
}}
>
<View style={styles.container}>
<View style={styles.listContainer}
>
<FlatList
data={this.state.myGamesArray}
renderItem={({ item }) => (
console.log(item.background_image),
<Card style={{flexDirection:'row',paddingEnd:100}}>
<CardItem cardBody>
<View>
<Image
style={styles.listImage}
source={{uri: item.background_image}}
/>
</View>
</CardItem>
<CardItem>
<View>
<Text style={styles.usergameText}>
{item}
</Text>
<Text style={styles.usergameText}>
Playstation 4
</Text>
</View>
</CardItem>
</Card>
)}
keyExtractor={(item,index) => index.toString()}
/>
</View>
<View>
<Header span
style={styles.header}>
<Autocomplete
inputContainerStyle={{borderColor:'transparent'}}
style={styles.autocompleteInput}
autoCapitalize="none"
autoCorrect={false}
//data to show in suggestion
data={games.length === 1 && comp(query, games[0].name) ? [] : games}
//default value if you want to set something in input
defaultValue={query}
/*onchange of the text changing the state of the query which will trigger
the findGame method to show the suggestions*/
onChangeText={text => this.setState({ query: text })}
placeholder=" Adicione os jogos que você tem"
//This below is the 'list' of autocomplete options
renderItem={({ item }) => (
//you can change the view you want to show in suggestion from here
//I GET ERROR WHEN TRYING TO ERASE (PS4) IN TEXT BOX ***NEED TO CHECK THIS
<View style={styles.iconContainer} >
<TouchableOpacity onPress={() => this.setState({ query: item.name})}
style={styles.autocompleteList} >
<View>
<Image
style={styles.gameImage}
source={{uri: item.background_image}}
/>
</View>
<Text style={styles.gameText}>
`${item.name}`
</Text>
</TouchableOpacity>
</View>
)}
/>
</Header>
</View>
<TouchableOpacity
style={styles.addButton}
onPress={() => this.AddItemsToArray()}
>
<Entypo name="plus" size={50} color="#fff" />
</TouchableOpacity>
</View>
</TouchableWithoutFeedback>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#fff',
flex: 1,
},
autocompleteInput: {
borderWidth: 1,
backgroundColor: "#fff",
borderColor: '#7843FF',
height: 50,
marginTop: 70,
borderRadius:10,
},
autocompleteList: {
flex:1,
flexDirection: 'row',
borderWidth:0.5,
borderColor: '#7843FF',
paddingVertical: 5,
paddingRight: 60,
},
listContainer: {
flex: 1,
position: 'absolute',
left: 10,
right: 10,
top:150,
flexDirection:'column',
justifyContent: 'center',
borderColor: '#7843FF',
},
gameText: {
fontSize: 15,
marginLeft: 10,
marginRight:30,
marginVertical:10,
color: '#000',
textAlign: 'left',
justifyContent: 'center'
},
usergameText: {
fontSize:15,
textAlign: 'left',
alignSelf:'stretch',
color: '#000',
},
gameImage: {
flex: 3,
height: 60,
width: 60,
marginLeft:10,
borderRadius: 100,
},
listImage: {
flex: 3,
height: 110,
width: 90,
marginLeft:0,
},
addButton: {
height:50,
width: 50,
position: 'absolute',
left: 371,
top: 71,
backgroundColor: '#7843FF',
borderTopRightRadius: 10,
borderBottomRightRadius:10,
},
usergameImage: {
height: 100,
width: 100,
borderRadius: 100,
},
header: {
backgroundColor:'#67E6DC'
}
});
export default App;
I am trying to create dynamic TextInputs, and then saving the values of TextInput into another state by indexing through loops, but I am not getting the desired output.
I think the problem is in the loop because the console.log of the onChangeText for the value of i is always the number of TextInputs.
import React, { useState, useEffect } from 'react';
import { StyleSheet, Text, View,TextInput, FlatList, Button, } from 'react-native';
export default function App() {
const [value,setValue]=useState(1)
const[textInput,setTextInput]=useState([])
const[inputData,setInputData]=useState([{index:0,text:''},{index:1,text:''},{index:2,text:''}])
useEffect(()=>{
addTextInput()
},[value])
const addTextInput=()=>{
var Input=[];
for(var i=0;i<value;i++){
Input.push(
<TextInput style={styles.textInput}
onChangeText={(text)=>{
var newarray = [...inputData]
var index = newarray.findIndex((dd) =>dd.index==i)
console.log('index',index,'i',i); //------>idk why but the value of i is always the no of text
// input pls hwlp me with
// these loop.i think i have done something wrong in here
newarray[index] = {index:i,text:text}
setInputData(newarray)} }
/>)
}
setTextInput(Input);
}
return (
<View style={styles.container}>
<View style={{height:50,color:'green',backgroundColor:'green',marginBottom:20}}/>
<View style={{flexDirection:'row',justifyContent:'space-around'}}>
<Text style={{fontSize:20,alignSelf:'center'}}>No Of Tenents:</Text>
</View>
<View style={{flexDirection:'row',justifyContent:'space-around'}}>
<Button title='1' onPress={()=>setValue(1)}/>
<Button title='2' onPress={()=>setValue(2)}/>
<Button title='3' onPress={()=>setValue(3)} />
</View>
<FlatList data={textInput}
renderItem={({item})=>{
return item
}}/>
</View>
);
}
const pickerSelectStyles = StyleSheet.create({
inputIOS: {
fontSize: 16,
paddingVertical: 12,
paddingHorizontal: 10,
borderWidth: 1,
borderColor: 'gray',
borderRadius: 4,
color: 'black',
paddingRight: 30,
},
inputAndroid: {
fontSize: 16,
paddingHorizontal: 10,
paddingVertical: 8,
borderWidth: 1,
borderColor: 'green',
borderRadius: 8,
color: 'black',
paddingRight: 50,
},
});
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
textInput: {
height: 40,
borderColor: 'black',
borderWidth: 1,
margin: 20
},
});
Use let in loop to declared i, because let can be only available inside the scope it's declared.[read this]
If you want remove loop,
const addTextInput = () => {
var Input = [...textInput];
if (Input.length < value) {
const InputIndex = Input.length;
Input.push(
<TextInput
style={styles.textInput}
onChangeText={text => {
var newarray = [...inputData];
const index = newarray.findIndex(dd => dd.index === InputIndex);
newarray[index] = {index: index, text: text};
setInputData(newarray);
console.log(newarray);
}}
/>,
);
} else {
Input.pop();
}
setTextInput(Input);
};
Using let instead of var solved my isuue.