I am learning React Native and i am trying to display some dynamic data using for loop and arrow function.
I am facing issues exactly data is not showing on screen but inside log it is printing for loop data.
What is wrong in this code ? As i am only able to see 49 as a value in console.warn.
Code
import React, { Component } from 'react';
import { StyleSheet, View, Text, ScrollView, Platform, Alert } from 'react-native';
export default class MyApp extends Component {
constructor() {
super();
}
dynamicList = () => {
var myloop = [];
for (let i = 0; i < 50; i++) {
console.warn(i)
myloop.push(
<View key={i} style={styles.item}>
<Text style={styles.item_text_style} onPress={() => { Alert.alert('Alert', `Title ${i.toString()}`) }}>Title {i}</Text>
<View style={styles.item_separator} />
</View>
);
}
}
render() {
return (
<ScrollView>
<View >
<Text >Welcome to React Native!</Text>
{this.dynamicList()}
</View>
</ScrollView>
);
}
}
const styles = StyleSheet.create(
{
MainContainer:
{
flex: 1,
paddingTop: 25
},
item_text_style:
{
fontSize: 20,
color: '#000',
padding: 10
},
item_separator:
{
height: 1,
width: '100%',
backgroundColor: '#263238',
}
});
wrap your function in componentDidMount() above render, like
componentDidMount(){
this.dynamicList()
}
Also, you are pushing your items in an array, so should use javasSript map method to display the key value pairs from an array
Please update your dynamicList function to following
dynamicList = () => {
var myloop = [];
for (let i = 0; i < 50; i++) {
console.warn(i)
myloop.push(
<View key={i} style={styles.item}>
<Text style={styles.item_text_style} onPress={() => { Alert.alert('Alert', `Title ${i.toString()}`) }}>Title {i}</Text>
<View style={styles.item_separator} />
</View>
);
}
return myloop;
}
Related
So I have tried to implement this code from user illusionist from another issue concerning auto filling text input with suggested text here in react native LINK: How to get suggestions while typing in text-input in react-native
this is how I implemented it >
import { Menu, TextInput } from "react-native-paper";
import React, { useState } from "react";
const Autocomplete = ({
value: origValue,
label,
data,
containerStyle,
onChange: origOnChange,
icon = 'bike',
style = {},
menuStyle = {},
right = () => {},
left = () => {},
}) => {
const [value, setValue] = useState(origValue);
const [menuVisible, setMenuVisible] = useState(false);
const [filteredData, setFilteredData] = useState([]);
const filterData = (text) => {
return data.filter(
(val) => val?.toLowerCase()?.indexOf(text?.toLowerCase()) > -1
);
};
return (
<View style={[containerStyle]}>
<TextInput
onFocus={() => {
if (value.length === 0) {
setMenuVisible(true);
}
}}
// onBlur={() => setMenuVisible(false)}
label={label}
right={right}
left={left}
style={style}
onChangeText={(text) => {
origOnChange(text);
if (text && text.length > 0) {
setFilteredData(filterData(text));
} else if (text && text.length === 0) {
setFilteredData(data);
}
setMenuVisible(true);
setValue(text);
}}
value={value}
/>
{menuVisible && filteredData && (
<View
style={{
flex: 1,
backgroundColor: 'white',
borderWidth: 2,
flexDirection: 'column',
borderColor: 'grey',
}}
>
{filteredData.map((datum, i) => (
<Menu.Item
key={i}
style={[{ width: '100%' }, menuStyle]}
icon={icon}
onPress={() => {
console.log(datum)
setValue(datum);
console.log(value)
setMenuVisible(false);
}}
title={datum}
/>
))}
</View>
)}
</View>
);
};
export default Autocomplete;
and in another page I import autocomplete and like here:
const [typZavady, setTypZavady] = useState('');
<Autocomplete
value={''}
style={[novaStyle.input]}
containerStyle={novaStyle.autocompleteContainer}
label="Typ závady"
data={['Svetla', 'Stoličky', 'Tabula', 'Projektor', 'Topenie', 'Počítače', 'Dvere', 'Iné']}
menuStyle={{backgroundColor: 'white'}}
onChange={newTyp => setTypZavady(newTyp)}
/>
However when I type and click on one of the suggested words only the part of the word I type in is stored in the const typZavady not the selected suggested word. I fiddled a bit with the code with no luck.
I am developing an app in android using react-native. The problem is when I use WebView, it only works on some devices, mostly the ones with older OS on android.
I have tried using this code and modified it a bit. It worked on some phones, but the elements inside the webview doesn't show in my own phones.
It renders like this, while it should have rendered something like this
Here is the snippet of ListSoal.js that contains the code to the WebView
import React, { Component } from 'react'
import {
ScrollView,
TouchableOpacity,
Alert,
Image,
Modal,
Text,
BackHandler,
WebView,
AsyncStorage,
Dimensions,
Platform
} from 'react-native'
const injectedScript = function () {
function waitForBridge () {
if (window.postMessage.length !== 1) {
setTimeout(waitForBridge, 200)
} else {
let height = 0
if (document.documentElement.clientHeight > document.body.clientHeight) {
height = document.documentElement.clientHeight
} else {
height = document.body.clientHeight
}
}
window.postMessage(height)
}
waitForBridge()
}
export default class ListSoal
extends Component {
state = {
webViewHeight: Number,
webViewHeightAnswer: Number
}
static defaultProps = {
autoHeight: true,
autoHeightAnswer: true
}
constructor (props) {
super(props)
this.state = {
webViewHeight: this.props.defaultHeight,
webViewHeightAnswer: this.props.defaultHeight
}
this._onMessage = this._onMessage.bind(this)
this._onMessageAnswer = this._onMessageAnswer.bind(this)
}
_onMessage (e) {
this.setState({
webViewHeight: parseInt(e.nativeEvent.data)
})
}
_onMessageAnswer (e) {
this.setState({
webViewHeightAnswer: parseInt(e.nativeEvent.data)
})
}
render () {
const { loading } = this.state
if (loading === true) {
return <CommonIndicator color={'#eb6a16'} size={'large'} />
}
if (this.state.soals.length <= 0) {
return (
<View style={styles.notContent}>
<Text style={styles.textNull}>{strings.exercises.notExercises}</Text>
</View>
)
}
const _w = this.props.width || Dimensions.get('window').width - '5%'
const _wA = this.props.width || 265
const _h = this.props.autoHeight ? this.state.webViewHeight : this.props.defaultHeight
const _hA = this.props.autoHeightAnswer ? this.state.webViewHeightAnswer : this.props.defaultHeight
const { animate, soals, no, totalQuestion, displayNumber, selected } = this.state
return (
<View style={styles.mainContainer}>
<View style={styles.topButtonGroup}>
<View style={{flexDirection: 'row', width: '100%', justifyContent: 'space-between'}}>
<View style={{width: '50%'}}>
<TouchableOpacity
onPress={() => this.onNumberModal()}
style={styles.btnNumber}>
<Text style={styles.textbutton}>{strings.exercises.number}</Text>
</TouchableOpacity>
</View>
<View style={{width: '50%'}}>
{
loading === true
? null
: soals[no].question.solution_id === null
? <View
style={[styles.btnSale, {backgroundColor: '#dddddd'}]}>
<Text style={styles.textbutton}>{strings.exercises.solution}</Text>
</View>
: <TouchableOpacity
onPress={() => this.checkSolution()}
style={styles.btnSale}>
<Text style={styles.textbutton}>{strings.exercises.solution}</Text>
</TouchableOpacity>
}
</View>
</View>
<View style={{flex: 1}} />
</View>
<View style={styles.backgquestion}>
<ScrollView>
<View animation={animate} duration={1100} style={styles.listquestion}>
<View style={styles.modal}>
<Text style={styles.number}>Number: {displayNumber + 1}</Text>
</View>
{
soals[no].question.image === null ? null : <Image resizeMode={'stretch'} source={{uri: config.storageUrl + soals[no].question.image}} style={styles.imagequestion} />
}
<View style={styles.soals}>
<WebView
scalesPageToFit={Platform.OS !== 'ios'}
ref={(ref) => { this.webview = ref }}
injectedJavaScript={'(' + String(injectedScript) + ')();'}
scrollEnabled={this.props.scrollEnabled || false}
onMessage={this._onMessage}
javaScriptEnabled={true}
automaticallyAdjustContentInsets={true}
{...this.props}
source={{html: soals[no].question.question}}
style={[{width: _w}, this.props.style, {height: _h}]}
/>
</View>
I have tried changing flex properties many times, but it seems that the problem comes from height = document.body.clientHeight or height document.elementBody.clientHeight because when I changed it to an integer, it worked.
Any suggestions? Thanks in advance
I have a flatlist and inside flatlist I Have a radioform. I have 2 items of radioform 'P' and 'A' Here is the picture of that
Here I need to post the selected item.My Problem is if I select P then all row value is P when I post and if I select A all row value is A . I have a logic that I have to get the row id wise state get to post . Here so far I have code
export default class attendancetest extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
rollno:"",
typeofattendance:1,
animating: true
};
}
componentWillMount() {
this.fetchData();
}
fetchData = async () => {
const response = await
fetch("http://192.168.1.208:8082/students/all");
const json = await response.json();
this.setState({ data: json });
};
closeActivityIndicator = () =>
setTimeout(
() =>
this.setState({
animating: false
}),
4000
);
componentDidMount = () => this.closeActivityIndicator();
render() {
const animating = this.state.animating;
return (
<View
style={--Style Code
}
>
<Logo />
<Text style={styles.titleText1}>
Test Section A Class 11th
</Text>
<ActivityIndicator
--Some Code
/>
<View style={styles.container}>
<Text style={styles.titleText}>Roll & Name Present Or Absent</Text>
</View>
<FlatList
data={this.state.data}
// rollno={this.state.data.rollno}
showsVerticalScrollIndicator={false}
renderItem={({ item,index }) => (
<View
style=--Style Code
>
<Text
style=--style code
>
{item.rollno}
--
{item.name}
</Text>
<RadioForm
animation={true}
buttonColor={"#C2E3A9"}
index={1}
formHorizontal={true}
labelHorizontal={true}
buttonStyle={{ marginRight: 20 }}
radioStyle={{ paddingRight: 20 }}
// labelHorizontal={false}
style={{
flex: 1,
paddingRight: 20,
flexDirection: "row",
width: 30
}}
radio_props={radio_props}
initial={this.state.typeofattendance}
// initial={value => {
// this.setState({ value: value });}}
isSelected = {true}
// radio_props
onPress={value => { index=
this.setState({ typeofattendance: value });
}}
ItemSeparatorComponent={this.renderSeparator}
/>
</View>
)}
// keyExtractor={(x, i) => i}
keyExtractor={(item, index) => index.toString()}
/>
<Button title="Submit" onPress={() => this.insert()} />
</View>
);
}
insert = () => {
var numstudent = this.state.data.length;
var datatest=[]
var data1;
for(var i=0;i<numstudent;i++){
data1={"rollno": this.state.data[i].rollno, "typeofattendence":
this.state.typeofattendance};
datatest.push(data1);
}
console.log(datatest);
}
}
Here this portion I can get P to A but not in particular row
</View>
onPress={value => {
this.setState({ typeofattendance: value });
}}
How to get row wise state get inside flatlist .
Here in these portion I check the radiobutton check item in button click
var numstudent = this.state.data.length;
var datatest=[]
var data1;
for(var i=0;i<numstudent;i++){
data1={"rollno": this.state.data[i].rollno, "typeofattendence": this.state.typeofattendance};
datatest.push(data1);
}
// console.log(datatest);
I have a FlatList to display list of users, when I change the device language to arabic, RTL is not rendered correctly. The arrows should be pointing the other way.
Here is the screenshot of how it looks on mobile.
Could you suggest if I am missing anything.
Here is my code.
FlatListScreen.js
import React, {Component} from 'react';
import {View, Text, FlatList} from 'react-native';
import {List, ListItem, SearchBar} from 'react-native-elements';
class FlatListScreen extends Component{
constructor(props) {
super(props);
this.state = {
loading: false,
date: [],
page: 1,
seed: 1,
error: null,
refreshing: false
};
}
componentDidMount(){
this.makeRemoteRequest();
}
makeRemoteRequest = () => {
const {page, seed } = this.state;
const url = 'https://randomuser.me/api/?seed=${seed}&page=${page}&results=20';
this.setState({loading: true});
fetch(url)
.then(res => res.json())
.then(res => {
this.setState({
data: page === 1 ? res.results : [...this.state.data, ...res.results],
error: res.error || null,
loading: false,
refreshing: false
});
})
.catch(error => {
this.setState({error, loading: false});
});
};
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: '86%',
backgroundColor: '#CED0CE',
marginLeft: '14%',
}}
/>
);
};
renderFooter = () => {
if(!this.state.loading) return null;
return (
<View
style={{
paddingVertical: 20,
borderTopWidth: 1,
borderTopColor: "#CED0CE"
}}
/>
)
};
renderHeader = () => {
return <SearchBar
placeholder="Search.."
lightTheme
round />;
}
onLearnMore = (item) => {
this.props.navigation.navigate('Profile', { ...item });
};
render (){
return (
<List containerStyle={{ borderTopWidth: 0, borderBottomWidth: 0}}>
<FlatList
data = {this.state.data}
renderItem={({item}) => (
<ListItem
roundAvatar
title={`${item.name.first} ${item.name.last}`}
subtitle={item.email}
avatar={{uri: item.picture.thumbnail}}
containerStyle={{ borderBottomWidth: 0 }}
onPress={() => this.onLearnMore(item)}
/>
)}
keyExtractor = {item => item.email}
ItemSeparatorComponent={this.renderSeparator}
ListHeaderComponent={this.renderHeader}
ListFooterComponent={this.renderFooter}
/>
</List>
)
}
}
export default FlatListScreen;
From the React-native documentation I have added following code for RTL support
https://facebook.github.io/react-native/blog/2016/08/19/right-to-left-support-for-react-native-apps.html#writing-rtl-ready-components
MainActivity.java
#Override
protected String getMainComponentName() {
I18nUtil sharedI18nUtilInstance = I18nUtil.getInstance();
sharedI18nUtilInstance.allowRTL(context, true);
return "navapp";
}
AndroidManifest.xml
<application
android:name=".MainApplication"
android:label="#string/app_name"
android:icon="#mipmap/ic_launcher"
android:allowBackup="false"
android:theme="#style/AppTheme"
android:supportsRtl="true">
Arrows showing in your FlatList are coming from the ListItem component you are using to show every record in your data. You need to check for the current language/RTL support and render arrow accordingly.
To achieve desired behavior you can use rightIcon property for ListItem component.
rightIcon
icon configuration for right icon (optional), either a name from the
icon library (like material) or a React Native element like Image.
Shows up unless hideChevron is set
Sample
<ListItem
roundAvatar
title={'title'}
subtitle={'sub title'}
avatar={{uri: item.picture.thumbnail}}
containerStyle={{ borderBottomWidth: 0 }}
onPress={() => this.onLearnMore(item)}
rightIcon={{name: (I18nManager.isRTL ? 'chevron-left': 'chevron-right')}}
/>
I want to implement a flip effect in my React Native app, similar like described here:
https://www.codementor.io/reactjs/tutorial/building-a-flipper-using-react-js-and-less-css
My question is. Can I achieve it somehow with the help of some library like 'Animations' https://facebook.github.io/react-native/docs/animations.html or I have to play with 'plain' CSS styles.
What is the 'good practive' for such animations in React Native?
class CardBack extends Component {
render() {
return (
<TouchableOpacity onPress={this.flip}>
<View style={styles.scrumCardBorder}>
<View style={styles.cardBack}>
</View>
</View>
</TouchableOpacity>
);
}
flip() {
this.setState({flipped: !this.state.flipped})
}
}
class CardFront extends Component {
render() {
return (
<TouchableOpacity>
<View style={styles.scrumCardBorder}>
<View style={styles.cardFront}>
<Text style={styles.cardValue}>5</Text>
</View>
</View>
</TouchableOpacity>
);
}
}
We can use transform and Interpolate to make 3D rotate Animation.
class RotateAnimation extends React.Component {
_rotateValue = new Animated.Value(0);
startAnimated = () => {
Animated.timing(this._rotateValue, {
toValue: 360,
duration: 800,
useNativeDriver: true
}).start()
}
getTransform = () => {
const rotate = this._rotateValue.interpolate({
inputRange: [0, 180, 360],
outputRange: ['0deg', '180deg', '360deg'],
extrapolate: 'clamp',
})
if (this.props.horizontal) {
return {
transform: {
perspective: WINDOW_WIDTH,
rotateX: rotate
}
}
}
return {
transform: {
perspective: WINDOW_WIDTH,
rotateY: rotate
}
}
}
render() {
return (<Animated.View style={[style, ]} />
{this.props.children}
</Animated.View>)
}
}
If you want to use transform around a certain point. Can try this.
Use Animated api for these transformations.
Note: Rotation along the axis(ie, rotateX or rotateY) with perspective will give you the feel of flipping.
Always use useNativeDriver: true for better performance.
Example code:
import React, {Component} from 'react';
import {View, Animated, StyleSheet, Button} from 'react-native';
export default class Container extends Component {
constructor() {
super();
this.animation = new Animated.ValueXY({x: 0, y: 0});
const inputRange = [0, 1];
const outputRange = ['0deg', '180deg'];
this.rotateX = this.animation.x.interpolate({inputRange, outputRange});
this.rotateY = this.animation.y.interpolate({inputRange, outputRange});
}
flip = (val) => {
this.animation[val].setValue(0);
Animated.timing(this.animation[val], {
toValue: 1,
duration: 500,
useNativeDriver: true,
}).start();
};
render() {
const {rotateX, rotateY} = this;
return (
<View style={styles.container}>
<Animated.View
style={{
...styles.item,
transform: [{rotateX}, {rotateY}, {perspective: 500}],
}}
/>
<Button title="flip x " onPress={() => this.flip('x')} />
<Button title="flip y " onPress={() => this.flip('y')} />
</View>
);
}
}
const styles = StyleSheet.create({
container: {flex: 1, alignItems: 'center', justifyContent: 'center'},
item: {
height: 200,
width: 200,
backgroundColor: 'red',
marginBottom: 20,
},
});