Related
i've seen alot of people having the same problem but sadly without any solutions .
I'm using expo with react native gesture handler, i have added "react-native-reanimated/plugin" in babel.config.js but still not getting any response.
Here is my code:
babel.config.js
module.exports = function (api) {
api.cache(true);
return {
presets: ["babel-preset-expo"],
plugins: ["react-native-reanimated/plugin"],
};
};
App.js
import { PanGestureHandler } from "react-native-gesture-handler";
import "react-native-gesture-handler";
import Animated, {
useAnimatedGestureHandler,
useAnimatedStyle,
useSharedValue,
} from "react-native-reanimated";
import { StyleSheet, View } from "react-native";
const SIZE = 100.0;
export default function App() {
const translateX = useSharedValue(0);
const panGestureEvent = useAnimatedGestureHandler({
onStart: (event) => {
console.log("starting...");
},
onActive: (event) => {
// translateX.value = event.translationX;
console.log(event.translationX);
},
onEnd: (event) => {},
});
const rStyle = useAnimatedStyle(() => {
return {
transform: [{ translateX: translateX.value }],
};
});
return (
<View style={styles.container}>
<PanGestureHandler onGestureEvent={panGestureEvent}>
<Animated.View style={[styles.square, rStyle]} />
</PanGestureHandler>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
square: {
width: SIZE,
height: SIZE,
backgroundColor: "dodgerblue",
borderRadius: 15,
},
});
i didn't do anything smart, simple and easy code, yet not getting any response.
package.json
{
"name": "a",
"version": "1.0.0",
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject"
},
"dependencies": {
"expo": "~44.0.0",
"expo-status-bar": "~1.2.0",
"react": "17.0.1",
"react-dom": "17.0.1",
"react-native": "0.64.3",
"react-native-web": "0.17.1",
"react-native-gesture-handler": "~2.1.0",
"react-native-reanimated": "^2.3.1"
},
"devDependencies": {
"#babel/core": "^7.12.9"
},
"private": true
}
On Android you need to wrap everything with GestureHandlerRootView.
So do this below
import {
GestureHandlerRootView,
} from 'react-native-gesture-handler';
then
<GestureHandlerRootView style={{ flex: 1 }}>
<View style={styles.container}>
<PanGestureHandler onGestureEvent={panGestureEvent}>
<Animated.View style={[styles.square, rStyle]} />
</PanGestureHandler>
</View>
</GestureHandlerRootView>
Related documentation: https://docs.swmansion.com/react-native-gesture-handler/docs/installation#js
I have deleted node_modules and rerun npm install. After that i got this error:
Error while updating property 'fontSize' in shadow node of type: RCTText
Value for fontSize cannot be cast from String to Double
I change all fontSize in form of fontSize:'20' to fontSize:20 but the error showing again. Now I removed fontSize property in all files and again error exist.
here is my package.json content:
{
"name": "myApp",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"test": "jest"
},
"dependencies": {
"jetifier": "^1.6.4",
"native-base": "^2.13.8",
"prop-types": "^15.7.2",
"react": "16.8.3",
"react-native": "0.59.8",
"react-native-dialog": "^5.6.0",
"react-native-gesture-handler": "^1.5.0",
"react-native-ionicons": "^4.6.3",
"react-native-material-dropdown": "^0.11.1",
"react-native-responsive-screen": "^1.3.0",
"react-native-slideshow": "^1.0.1",
"react-navigation": "^3.13.0"
},
"devDependencies": {
"#babel/core": "7.4.4",
"#babel/runtime": "7.4.4",
"babel-jest": "24.8.0",
"jest": "24.8.0",
"metro-react-native-babel-preset": "0.54.0",
"react-test-renderer": "16.8.3"
},
"jest": {
"preset": "react-native"
},
"rnpm": {
"assets": [
"./assets/fonts"
]
}
}
UPDATE:
MainPage of the app:
import React, { Component } from 'react';
import { View, Text,StyleSheet,Image,TouchableWithoutFeedback } from 'react-native';
import Slideshow from 'react-native-slideshow';
import {widthPercentageToDP as wp, heightPercentageToDP as hp} from 'react-native-responsive-screen';
import Colors from '../Colors';
import Strings from '../Strings';
import DrawerNavigator from '../routes/DrawerNavigator';
class AppMainPage extends Component {
constructor(props) {
super(props);
this.state = {
position: 0,
interval: null,
dataSource: [],
sliderSource:[]
};
}
componentDidMount(){
this.fetchSliderImage();
}
componentWillMount() {
this.setState({
interval: setInterval(() => {
this.setState({
position: this.state.position === this.state.dataSource.length-1 ? 0 : this.state.position + 1
});
}, 2000)
});
}
componentWillUnmount() {
clearInterval(this.state.interval);
}
getAuthAndReload(){
ajax.fetchAuth().then(()=>{this.fetchSliderImage()});
}
async fetchSliderImage(){
try{
let response = await fetch(Strings.baseUrl+'spanser/new?type=1&ostanId=1', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' +Strings.id_token
}
}).then((resp) => {
return resp.json()
})
.then((responseJson) => {
const json_data = responseJson;
if("title" in responseJson && responseJson.title=="Unauthorized" ){
this.setState({loadData:1},()=>this.getAuthAndReload());
return 0;
}
else{
const arr = Object.keys(json_data).map(function(_) { return json_data[_]; });
var resultArray=new Array();
for(i=0;i<arr.length;i++){
resultArray.push({'title':arr[i].title,'caption':'','url':Strings.imageUrl+arr[i].image1});
}
this.setState({sliderSource:resultArray,dataSource:arr});
return arr;
}
});
}
catch (error) {
console.error(error);
}
}
onImageClick(){
console.log('&&'+this.state.dataSource[0]);
console.log('******'+this.state.position);
this.props.navigation.navigate('SponserPage',{currentItem:this.state.dataSource[this.state.position]})
}
render() {
return (
<View style={{backgroundColor:'black',flex:1}}>
<DrawerNavigator/>
<View style={styles.rowViews}>
<View style={styles.columnViews}>
<Image style={styles.imgStyle} source={require('../Icons/play-button.png')}/>
<Text style={styles.txtStyle}>ویدیوی ویژه</Text>
</View>
<View style={styles.columnViews}>
<Image style={styles.imgStyle} source={require('../Icons/star.png')}/>
<Text style={styles.txtStyle}>پیشنهادهای ویژه</Text>
</View>
<View style={styles.columnViews}>
<Image style={styles.imgStyle} source={require('../Icons/irandokht.png')}/>
<TouchableWithoutFeedback onPress={()=>this.props.navigation.navigate('SalonList')}>
<Text style={styles.txtStyle}>لیست سالنها</Text></TouchableWithoutFeedback>
</View>
</View>
<View style={{width:'100%',height:2,backgroundColor:Colors.yellow}}/>
<View style={styles.rowViews}>
<View style={styles.columnViews}>
<Image style={styles.imgStyle} source={require('../Icons/trophy.png')}/>
<Text style={styles.txtStyle}>برندگان مسابقات</Text>
</View>
<View style={styles.columnViews}>
<Image style={styles.imgStyle} source={require('../Icons/trophy(1).png')}/>
<Text style={styles.txtStyle}>سالن برتر ماه</Text>
</View>
<TouchableWithoutFeedback style={styles.columnViews} onPress={()=>this.props.navigation.navigate('Mosabeqat')}>
<View >
<Image style={styles.imgStyle} source={require('../Icons/medal.png')}/>
<Text style={styles.txtStyle}>شرکت در مسابقه </Text>
</View>
</TouchableWithoutFeedback>
</View>
<View style={styles.rowViews}>
<View style={styles.columnViews}>
<Image style={styles.imgStyle} source={require('../Icons/contact.png')}/>
<Text style={styles.txtStyle}>ارتباط با ایران دخت</Text>
</View>
<TouchableWithoutFeedback style={styles.columnViews} onPress={()=>this.props.navigation.navigate('MajaleyeTakhasosi')}>
<View >
<Image style={styles.imgStyle} source={require('../Icons/open-magazine.png')}/>
<Text style={styles.txtStyle}>مجله تخصصی</Text>
</View>
</TouchableWithoutFeedback>
<View >
<Image style={styles.imgStyle} source={require('../Icons/newspaper.png')}/>
<TouchableWithoutFeedback style={styles.columnViews} onPress={()=>this.props.navigation.navigate('NewsNav')}>
<Text style={styles.txtStyle}>اخبار مهم</Text>
</TouchableWithoutFeedback></View>
</View>
<View style={styles.columnViews}>
{this.state.sliderSource.length>0?
<Slideshow
containerStyle={{padding: 10,}}
dataSource={this.state.sliderSource}
position={this.state.position}
resizeMode='contain'
onPositionChanged={position => this.setState({ position:position })}
onPress={()=>{this.onImageClick()}}/>
:
<View/>
}
</View>
</View>
);
}
}
const styles=StyleSheet.create(
{
rowViews:{
flexDirection:'row',
justifyContent: 'space-between',
alignItems: 'center',
margin:10,
flex:1
},
columnViews:{
flexDirection:'column',
justifyContent: 'center',
alignItems: 'center',
margin: 5,
},
txtStyle:{
fontFamily: 'BYEKAN',
color:'white'
},
imgStyle:{
height:hp('20%'),
width:wp('20%'),
resizeMode:'contain'
}
}
)
export default AppMainPage;
I don't know how to fix error. thanks for any help
these are photo of error:
this can be solved be using:
fontSize: 20
instead of:
fontSize: "20px"
or
fontSize: '20px'
..apparently its expecting a number and not a string. PS, string works well on the iOS device but gives error on the Android device.
If you have a package.lock file or yarn.lock, delete it, delete the node_modules folder and run
npm cache clean --force
then run:
npm install or yarn install
Somewhere you are changing your fontSize from string to double it could be text as well icons if you are using icons somewhere,
I was having the same issue solved giving equivalent datatype to every where i'm using font or icons
react-native link.
I have deleted the previous line of code where I got this error and ran server again add the code and run server.
By this issue resolved for me.
I had the same problem, but I discovered that I should use only double quotes "" Always use Double in your style.
const styles=StyleSheet.create(
{
rowViews:{
flexDirection:"row",
justifyContent: "space-between",
alignItems: "center",
margin:10,
flex:1
},
columnViews:{
flexDirection:"column",
justifyContent: "center",
alignItems: "center",
margin: 5,
},
txtStyle:{
fontFamily: "BYEKAN",
color:"white"
},
imgStyle:{
height:hp("20%"),
width:wp("20%"),
resizeMode:"contain"
}
}
)
It takes number not string
ex. fontSize:19,
what's wrong with my code why wont it add the font to my app
I'm getting this error fontFamily "open-sans" is not a system font and has not been loaded through Font.loadAsync.
If you intended to use a system font, make sure you typed the name correctly and that it is supported by your device operating system.
mport React from 'react';
import { View, Text } from 'react-native';
import { Font } from 'expo';
this.state = {
fontLoaded: false,
}
Im using Font.loadAsync did i write it wrong?
async componentDidMount() {
await Font.loadAsync({
'OpenSans-Bold': require('./assets/fonts/OpenSans-Bold.ttf')
}).then(() => {
this.setState({ fontLoaded: true });
});
}
return (
<View style={styles.container}>
{ this.state.fontLoaded === true ? (
<React.Fragment>
</React.Fragment>
) : (<Text style={styles.inputText}>Loading... </Text>)
}
</View>
inputText: {
fontSize: hp('3%'),
color: '#5D5D5D',
fontWeight: 'bold',
paddingVertical: hp('0.5%'),
paddingLeft: wp('6.5%'),
fontFamily: 'open-sans'
},
my pacakadge.json file
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject",
"rnpm": {
"assets": [
"./assets/fonts/"
]
}
}
From SDK 33 the built-in modules of Expo must be installed. So you have to install a font module.
You can run expo install expo-font
The font name you registered with is different from the font name you want to use. And the conditional statement is wrong. After loading the font, make the text visible.
Change your font name
import * as Font from 'expo-font';
...
this.state={
fontLoaded: false
}
async componentDidMount() {
await Font.loadAsync({
'OpenSans-Bold': require('./assets/fonts/OpenSans-Bold.ttf')
});
this.setState({ fontLoaded: true });
}
return (
<View style={styles.container}>
{ this.state.fontLoaded !== true ? (
<React.Fragment>
</React.Fragment>
) : (<Text style={styles.inputText}>Loading... </Text>)
}
</View>
inputText: {
fontSize: hp('3%'),
color: '#5D5D5D',
fontWeight: 'bold',
paddingVertical: hp('0.5%'),
paddingLeft: wp('6.5%'),
fontFamily: 'OpenSans-Bold'
},
I am trying to make dynamic screen where i am adding multiple CustomSpinners using forEach loop in react-native.
The problem I am facing is that whenever I am selecting value from any spinner that value gets updated for all spinners, as the index remains the same. Suppose when I click on color spinner and choose Cyna which is at index 2 and when I type this.setState({name: index}); it calls Render method again and the whole view get draw again and as the itemName={this.state.name} is set to 2 so it will auto select all the spinner values based on index 2 , what I want that when I tap on Color spinner and choose cyan color then only that Color spinner gets updated instead of updating all spinners at same index.
Can any one let me know how to achieve this? I am already scratching my head from past 2 days on this. Please let me know your suggestions that will really help me lot.
Here is my code :-
onClickColor(data) {
this.setState({ name: index });
}
renderSpinerData(item) {
return <CustomDynamicSpinner
title={"Chosse " + item.label}
listArray={item.options}
onClick={(data,index) => this.onClickDropdown(data,index)}
itemName={this.state.name}
btnStyle={{
height: 42,
marginBottom: 2,
borderBottomWidth: 1 / 2,
justifyContent: "center"
}}
txtColor={appColor.lightGrey}
style={{
height: 42,
marginBottom: 2,
borderBottomWidth: 1 / 2
}}
closeIconButtonStyle={styles.closeButtonStyle}
/>
};
renderConfigurableProductDetail() {
let array=[];
if (CustomConfigArray.length>0){
array = CustomConfigArray;
} else {
array = this.props.ProductDetailState.productData.configurable;
}
{
return array.map((item) => {
if(item.label!="Size"){
return (
<View style={{ flex: 1, backgroundColor: "white", flexDirection: "column", marginTop: 8 }}>
<CustomText style={{ fontSize: 16, fontFamily: "futuraLigtBt", marginLeft: 6, paddingLeft: 15, paddingRight: 15, paddingTop: 5, paddingBottom: 5 }}>
{item.label}
</CustomText>
{this.renderSpinerData(item)}
</View>;
)
}
})
}
};
My CustomSpiner class :-
class DynamicListViewModal extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: ds.cloneWithRows(this.props.listArray),
listArray: this.props.listArray
};
this.handleClick = this.handleClick.bind(this);
this.renderRow = this.renderRow.bind(this);
this.renderList = this.renderList.bind(this);
}
handleClick(data, index) {
this.props.onClick(data, index);
this.props.onClose();
}
renderRow(rowData) {
const separatorStyle = this.props.separatorStyle;
const rowTextStyle = this.props.rowText;
const rowStyle = this.props.rowStyle;
const rowId = this.props.listArray.indexOf(rowData);
let separator = <View style={separatorStyle} />;
let row = (
<View style={rowStyle}>
<Text style={rowTextStyle}>{rowData.label}</Text>
</View>
);
if (this.props.renderRow) {
row = this.props.renderRow(rowData, rowId);
}
return (
<View>
<TouchableOpacity onPress={() => this.handleClick(rowData, rowId)}>
{row}
</TouchableOpacity>
{separator}
</View>
);
}
renderList() {
const listViewStyle = this.props.listViewStyle || DefaultStyles.listView;
return (
<ListView
style={listViewStyle}
dataSource={this.state.dataSource}
renderRow={(rowData) => this.renderRow(rowData)}
automaticallyAdjustContentInsets={false}
enableEmptySections={true}
/>
);
}
render() {
const containerStyle = this.props.containerStyle;
const topBarStyle = this.props.topBarStyle;
const iconContainerStyle = this.props.iconContainerStyle;
const closeIconButtonStyle = this.props.closeIconButtonStyle;
const titleStyle = this.props.titleStyle;
const title = this.props.title;
return <View style={containerStyle}>
<View style={topBarStyle}>
<View style={iconContainerStyle} />
<Text style={[titleStyle, { fontWeight: "bold", fontSize: 17 }]}>
{title}
</Text>
<TouchableOpacity style={iconContainerStyle} onPress={() => this.props.onClose()}>
<Image source={require("../../assets/cancel.png")} style={closeIconButtonStyle} />
</TouchableOpacity>
</View>
{this.renderList()}
</View>;
}
}
class CustomDynamicSpinner extends Component {
constructor(props) {
super(props);
this.state = {
data: this.props.data,
popoverIsOpen: false
};
this.onClick = this.onClick.bind(this);
}
onClick(data) {
console.log("selected data:", data);
}
render() {
const onClick = this.props.onClick || this.onClick;
return <View>
<TouchableOpacity style={this.props.btnStyle} onPress={() => this.setState(
{ popoverIsOpen: true }
)}>
<Text style={{ color: this.props.txtColor }}>
{(this.props.itemName!="value" || this.props.itemName == 0) ? this.props.listArray[this.props.itemName].label : "Please select"}
</Text>
</TouchableOpacity>
<Modal animationType={"slide"} transparent={false} visible={this.state.popoverIsOpen} onRequestClose={() => {
console.log("Modal has been closed.");
}}>
<View>
<DynamicListViewModal listArray={this.props.listArray} title={this.props.title} onClick={onClick} onClose={() => this.setState(
{ popoverIsOpen: false }
)} containerStyle={this.props.containerStyle} listViewStyle={this.props.listViewStyle} separatorStyle={this.props.separatorStyle} topBarStyle={this.props.topBarStyle} titleStyle={this.props.titleStyle} iconContainerStyle={this.props.iconContainerStyle} closeIconButtonStyle={this.props.closeIconButtonStyle} rowTextStyle={this.props.rowTextStyle} rowStyle={this.props.rowStyle} />
</View>
</Modal>
</View>;
}
}
Response From Api :-
"configurable": [{
"id": "142",
"code": "size",
"label": "Size",
"options": [{
"attribute_id": "142",
"atribute_code": "size",
"id": "171",
"label": "XL",
"products": [
"2071",
"2074"
]
}, {
"attribute_id": "142",
"atribute_code": "size",
"id": "172",
"label": "L",
"products": [
"2072"
]
}]
},
{
"id": "93",
"code": "color",
"label": "Color",
"options": [{
"attribute_id": "93",
"atribute_code": "color",
"id": "50",
"label": "Blue",
"products": [
"2071"
]
},
{
"attribute_id": "93",
"atribute_code": "color",
"id": "60",
"label": "Black",
"products": [
"2072"
]
}, {
"attribute_id": "93",
"atribute_code": "color",
"id": "64",
"label": "Cyna",
"products": [
"2072"
]
}, {
"attribute_id": "93",
"atribute_code": "color",
"id": "61",
"label": "White",
"products": [
"2071",
"2074"
]
}
]
},
{
"id": "148",
"code": "format",
"label": "Format",
"options": [{
"attribute_id": "148",
"atribute_code": "format",
"id": "102",
"label": "Download",
"products": [
"2072",
"2071",
"2074"
]
},
{
"attribute_id": "148",
"atribute_code": "format",
"id": "103",
"label": "File",
"products": [
"2071",
"2074"
]
}
]
}
]
Your Help would be greatly appreciated !!!
Regards
When new state depends on previous state you should use the format setState((prevState, props) => {}) see reference in the docs. In any way you should never mutate state directly and this is what this line does selectValue[index] = value since selectValue is just a reference to this.state
So here is what exactly you need to do :-
// load selectedDropDownValue data from state with the item's id
// pass the item value to the change function
<Picker
selectedValue={this.state.selectedDropDownValue[item.id]}
onValueChange={(itemValue, itemIndex) => this.onClickDropdown(itemValue, itemIndex, item)}
>
{this.loadData(item)}
</Picker>
onClickDropdown(data, index, item){
// save each items selected data with their id
this.setState((prevState) => {
const value = Object.assign({}, prevState.selectedDropDownValue, { [item.id]: data});
return { selectedDropDownValue: value};
});
}
Your problem is that name is a part of the parental component's state. Whenever onClickColor is called, the parental component updates, forcing all spinners to re-render along with it.
Since your question has react-redux tag, I assume your app use redux as well. If that is the case, then the simplest solution is to move name into redux's store and let CustomDynamicSpinner read name directly from the store:
import { connect } from 'react-redux'
...
const mapStateToProps = (state) => ({
itemName: state.whateverPath.name
})
connect(mapStateToProps)(CustomDynamicSpinner)
And don't let the component containing CustomDynamicSpinner read name from redux's store. Shall any part in that component need that information, you should create an extra child component accessible to the store instead.
Is it possible to dynamically create and add view components in React Native?
For example, firstly I have only empty screen and information of all views come from server in JSON, and then it is need to generate them on the screen.
For example - application getting json from server. This json describes the screen that have to be builded:
{
"type": "linearlayout",
"subviews": [{
"type": "text",
"fields": {
"text": "This is text field"
},
"styles": {
"color": "",
"textSize": 14
}
}, {
"type": "button",
"fields": {
"text": "JUST BUTTON"
},
"transition": {
"name": "http://www.link.com"
}
}, {
"type": "text",
"fields": {
"text": "This is another text field"
},
"styles": {
"color": "",
"textSize": 18
}
}]
}
So, by that JSON I need dynamically views building in React Native. But I can't see any ability to write JS code inside JSX - only static views and dynamically changing of props
Yes this is possible. Assume that you retrieve your JSON data successfully and save it to some state then in your render function you can use it like that;
render() {
var productList = [];
this.state.data.products.forEach(function (tmpProduct) {
productList.push(
<View style={cardView} key={tmpProduct.id}>
<Grid style={upperGrid}>
<Col style={{flex: 0.5}}>
<Thumbnail
source={require('../../../images/sample-image.png')}
style={itemThumb}>
</Col>
<Col>
<Text style={cardItemHeader} numberOfLines={2}>{tmpProduct.title}</Text>
<Text style={cardItemBody} numberOfLines={2}>{tmpProduct.description}</Text>
</Col>
</Grid>
</View>
);
}.bind(this));
return (
<Container theme={theme}>
<Image source={require('../../../images/grad-bg.png')} style={background} >
<Content style={scrollContent}>
{productList}
</Content>
</Image>
</Container>
)
}
I hope this code piece give you an idea. You can adapt it to your case.
React docs (and by extension it could be done with ReactNative too) show how to choose the component type at runtime:
import React from 'react';
import { PhotoStory, VideoStory } from './stories';
const components = {
photo: PhotoStory,
video: VideoStory
};
function Story(props) {
const SpecificStory = components[props.storyType];
return <SpecificStory story={props.story} />;
}
Doing so, you could just only need to walk on your JSON tree and just create the ReactNative components, using the components object as a mapping between the type defined in the JSON tree and their constructors.
Here is another approach:-
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
const renderObject = {
type : "View",
children : [
{
type: "View",
styles: {
backgroundColor: "orange",
flex:1,
justifyContent:"center",
alignItems: "center"
},
children: [
{
type: "Text",
styles: {
color: "yellow",
fontSize: 20
},
text: "Hello"
},
{
type: "View",
styles: {
backgroundColor: "red",
width: 100,
height: 5,
marginTop: 10
},
children: []
}
]
},
{
type: "View",
styles: {
flex:1,
justifyContent:"center",
alignItems: "center"
},
children: [
{
type: "Text",
styles: {
color: "red",
fontSize: 40
},
text: "Hello"
}
]
},
{
type: "View",
styles: {
flex:1,
justifyContent:"center",
alignItems: "center",
backgroundColor: "green"
},
children: [
{
type: "Text",
styles: {
color: "white",
fontSize: 80
},
text: "Hello"
}
]
}
],
styles: {
flex:1
}
}
const CustomComp = (props) => {
const {type} = props;
if(type == "View"){
const {styles, children} = props;
return <View style={styles}>{children.map((item) => CustomComp(item))}</View>
} else if(type == "Text") {
const {styles, text} = props;
return <Text style={styles} >{text}</Text>
}
}
export default function App() {
return (
<View style={styles.container}>
{CustomComp(renderObject)}
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
justifyContent: 'center',
},
});
You can find the full code on this Repo.
Yes it is possible to dynamically create components in React Native based on data you retrieve from the server.
However, if you are wanting the app to check for the latest JS code (including new components/views) without requiring an update through app store, you could use something like code-push. https://microsoft.github.io/code-push/
Your question is somewhat vague so if I misunderstood then possibly you could give an example 'information of all views'.
One of the benefits of using react native (vs webview) is that your users won't be staring at empty screens when the app is loading data. If you return all views from server, then it works like web page. I have done something like that before. Believe me that's not the best UX. Ideally json response should only return data. Then client can be built with any framework (react native, iOS or Android native) and they share the same API endpoints.