以编程方式在React Native中添加组件

16

假设我有一个简单的React Native应用程序,如下所示:

'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);

当按下TouchableHighlight时,如何在第一个和第二个Text标签之间动态插入组件?


3
React 的设计哲学是将状态(State)映射到用户界面(UI),因此要改变 UI,需要改变状态(State)和属性(Props),而不是直接操纵 UI 元素。 - everlasto
React Native 是编译代码,因此您无法进行真正的动态操作。 - jack
4个回答

27

尝试创建一个数组并将其附加到状态。然后,您可以向数组中推送项目并重置状态。

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);

我已经在这里设置了一个工作示例


1
我理解你所做的事情,但那并不是我想要实现的。这不仅是关于显示和隐藏一个组件,我需要能够添加组件。按下一次按钮,你获得一个新组件。再按一次,你就获得第二个组件,依此类推。 - Axeva
1
抱歉之前的误解,我已经更新了示例和我的代码。 - Nader Dabit
2
这已经非常接近我所想要的了,谢谢。仍然有些困扰的是,你不能通过传递对其之前或之后的元素(或者容器)的引用来任意选择插入点,但至少这是一个可行的起点。 - Axeva
我的错误在于我只是将状态推送了一下。导致渲染的原因是调用了setState()。 - mdehghani

4
在React或React Native中,组件的隐藏/显示或添加/删除不像在Android或iOS中那样工作。大多数人认为会有类似的策略,例如View.hide = true或parentView.addSubView(childView),但React Native的工作方式完全不同。实现此类功能的唯一方法是将您的组件包含在DOM中或从DOM中删除它。
在这个例子中,我将根据按钮单击设置文本视图的可见性。 enter image description here 这个任务背后的想法是创建一个名为state的状态变量,初始值设置为false,当按钮点击事件发生时,它的值会切换。现在,我们将在组件创建期间使用此状态变量。
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>
    );
  }
}

在这段代码中需要注意的唯一一件事就是renderIf,它实际上是一个函数,根据传递给它的布尔值返回传递给它的组件。

renderIf(predicate)(element).

renderif.js

'use strict';
const isFunction = input => typeof input === 'function';
export default predicate => elemOrThunk =>
  predicate ? (isFunction(elemOrThunk) ? elemOrThunk() : elemOrThunk) : null;

3

使用 React 组件时,您不希望考虑操作到达 DOM 并插入组件 - 您希望考虑组件对动作的响应。理论上,该组件已经组合并准备好了,只需要知道是否应该进行渲染:

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>
    );
  }
});

我还制作了一个帮助程序,可以轻松地有条件地呈现事物,render-if
renderIf(this.state.show)(
  <Text>Yay</Text>
)

我的问题更多是关于动态性而不是显示和隐藏。如果用户按两次该按钮,我需要插入2个元素。如果他们按了10次,我需要添加10个。最终可能还会有一个删除按钮。这一切都是关于能够在屏幕上动态地添加或删除元素。 - Axeva

3

ECMA6语法

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",
    }
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接