Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically add a component in React Native

Suppose I have a simple React Native app like so:

'use strict';

var React = require('react-native');
var {
  AppRegistry,
  Text,
  TouchableHighlight,
  View,
} = React;

var ReactProject = React.createClass({
  _onPressOut: function() {
    // What do we do here?
  },

  render() {
    return (
      <View>
        <Text>This text should be before</Text>
        <Text>This text should be after</Text>
        <TouchableHighlight onPressOut={this._onPressOut}>
          <Text>Tap Me</Text>
        </TouchableHighlight>
      </View>
    );
  }
});

AppRegistry.registerComponent('ReactProject', () => ReactProject);

How can I dynamically insert a component between the first and second Text tags when the TouchableHighlight is pressed?

like image 864
Axeva Avatar asked Feb 18 '16 02:02

Axeva


4 Answers

Try creating an array and attaching it to the state. You can then push items to the array, and reset the state.

https://rnplay.org/apps/ymjNxQ

'use strict';

var React = require('react-native');
var {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  TouchableHighlight
} = React;

var index = 0

var SampleApp = React.createClass({

  getInitialState(){
    return { myArr: [] }
  },

  _onPressOut() {
    let temp = index ++
    this.state.myArr.push(temp)
    this.setState({
        myArr: this.state.myArr
    })
  },

  render() {

    let Arr = this.state.myArr.map((a, i) => {
      return <View key={i} style={{ height:40, borderBottomWidth:2, borderBottomColor: '#ededed' }}><Text>{ a }</Text></View>                            
    })    
    return (
      <View style={styles.container}>
        <Text>First</Text>
        { Arr }
        <Text>Second</Text>
        <TouchableHighlight style={ styles.button } onPress={ () => this._onPressOut() }>
            <Text>Push</Text>
        </TouchableHighlight>
      </View>
    );
  }
});

var styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop:60
  },
  button: {
    height:60,
    backgroundColor: '#ededed',
    marginTop:10,
    justifyContent: 'center',
    alignItems: 'center'
  }
});

AppRegistry.registerComponent('SampleApp', () => SampleApp);

I've set up a working example here.

like image 126
Nader Dabit Avatar answered Oct 19 '22 23:10

Nader Dabit


In react or react native the way component hide/show or add/remove does not work like in android or iOS. Most of us think there would be the similar stratedgy like

View.hide = true or parentView.addSubView(childView

But the way react native work is completely different. The only way to acheive this kind of functionality is to include your component in your DOM or remove from DOM.

Here in this example I am going set the visibility of text view based on the button click. enter image description here

enter image description here

The idea behind this task is the create a state variable called state having the initial value set to false when the button click event happens then it value toggles. Now we will use this state variable during the creation of component.

import renderIf from './renderIf'

class fetchsample extends Component {
  constructor(){
    super();
    this.state ={
      status:false
    }
  }
  toggleStatus(){

  this.setState({
    status:!this.state.status
  });
  console.log('toggle button handler: '+ this.state.status);
  }

  render() {
    return (
      <View style={styles.container}>
       {renderIf(this.state.status)(
         <Text style={styles.welcome}>
         I am dynamic text View
         </Text>
       )}

        <TouchableHighlight onPress={()=>this.toggleStatus()}>
          <Text> touchme </Text>
        </TouchableHighlight>
      </View>
    );
  }
}

the only one thing to notice in this snippet is renderIf which is actually a function which will return the component passed to it based on the boolean value passed to it.

renderIf(predicate)(element).

renderif.js

'use strict';
const isFunction = input => typeof input === 'function';
export default predicate => elemOrThunk =>
  predicate ? (isFunction(elemOrThunk) ? elemOrThunk() : elemOrThunk) : null;
like image 31
Rajan Twanabashu Avatar answered Oct 19 '22 23:10

Rajan Twanabashu


With React components you don't want to think of actions reaching into the DOM and inserting components - you want to think components responding to actions. Theoretically, this component is already composed and ready, it just needs to know if it should be rendered or not:

var ReactProject = React.createClass({
  getInitialState() {
    // our *state* dictates what the component renders
    return {
      show: false
    };
  }
  _onPressOut: function() {
    // update our state to indicate our "maybe" element show be shown
    this.setState({show: !this.state.show});
  },
  maybeRenderElement() {
    if (this.state.show) {
      // depending on our state, our conditional component may be part of the tree
      return (
        <Text>Yay!</Text>
      );
    }
    return null;
  }
  render() {
    return (
      <View>
        <Text>This text should be before</Text>
        {this.maybeRenderElement()}
        <Text>This text should be after</Text>
        <TouchableHighlight onPressOut={this._onPressOut}>
          <Text>Tap Me</Text>
        </TouchableHighlight>
      </View>
    );
  }
});

I've also made a helper that makes it easy to conditionally render things, render-if

renderIf(this.state.show)(
  <Text>Yay</Text>
)
like image 25
Atticus Avatar answered Oct 20 '22 00:10

Atticus


ECMA6 Syntax

import React, { Component } from 'react';
import {
View,
Text,
StyleSheet,    
TextInput,
TouchableOpacity,
TouchableHighlight
} from 'react-native';    

export default class fourD extends Component {

  constructor(props) {
    super(props);
    let ele1 = (
      <View key={1}>
        <Text>Element {1}</Text>
        <TouchableOpacity onPress={ () => this._add()  }>
         <Text>Add</Text>
        </TouchableOpacity>
      </View>
     );

    this.state = {
      ele: [],
      key: 1
    }

    this.state.ele.push(ele1);

   }

  _add(){

    let key = this.state.key + 1;

    let ele2 = (
      <View key={key}>
        <Text>Element {key}</Text>
        <TouchableOpacity onPress={ () => this._add()  }>
         <Text>Add</Text>
        </TouchableOpacity>
      </View>
    );

    let ele = this.state.ele;
    ele.push(ele2);
    this.setState({ ele: ele,key : key})

  }
  render() {

    return (
      <View style={styles.container}>
       <Text>This text should be before</Text>
        { this.state.ele }
       <Text>This text should be after</Text>
       <TouchableHighlight onPressOut={ () => this._add()  }>
          <Text>Tap Me</Text>
        </TouchableHighlight>
      </View>
    )
  }
}



const styles = StyleSheet.create({
    container: {
      flex: 1,
      backgroundColor: "white",
    }
})
like image 27
Abhishek Kumar Avatar answered Oct 20 '22 00:10

Abhishek Kumar