Natan Rubinstein
Natan Rubinstein

Reputation: 1893

Is it possible to dynamically create components in React Native?

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

Upvotes: 20

Views: 29608

Answers (5)

Honey Yadav
Honey Yadav

Reputation: 186

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.

Upvotes: 4

Piranna
Piranna

Reputation: 1740

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.

Upvotes: 6

milkersarac
milkersarac

Reputation: 3469

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.

Upvotes: 16

Haitao Li
Haitao Li

Reputation: 1713

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.

Upvotes: -1

Travis White
Travis White

Reputation: 1977

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'.

Upvotes: 1

Related Questions