Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React native listview add item not working

I am new to react native and I was implemented a simple idea in my head. Basically, I am doing a 'todo list' like component which theres a add button below and items can be added. The problem arises after clicking on the add button and the list gets updated and the following xcode warning message appears. And I have realised, after implementing the ListView, that the app in the simulator slows down so much i couldn't even inspect. The alert popup would freeze the UI after some text are entered too, and the entire app needs to be built again since I couldn't do anything. Thanks for all the help!

Main component: SurveyQn

'use strict'

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

var LongButton = require('./LongButton.js');

class SurveyQn extends Component {

constructor(props) {
    super(props);

    this.state = {
        options: [{option: 'Pizza'}],
    };
}

componentWillMount() {
    this.dataSource = new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2
    })
}

_renderItem(item) {
    return (
        <LongButton 
            text={item.option} 
            onPress={() => {}} 
            //btnViewStyle={styles.buttonView}
            //btnTextStyle={styles.buttonText}
        />
    );
}

_addItem() {
    AlertIOS.alert(
        'Add new option',
        null,
        [
            {
                text: 'Add',
                onPress: (text) => {
                    var options = this.state.options;
                    options.push({option: text})
                    this.setState({ options: options})
                }
            },
        ],
        'plain-text'
    );
}

render(){
    var dataSource = this.dataSource.cloneWithRows(this.state.options);
    return (
        <View style={styles.container}>
            <TextInput
                style={styles.question}
                placeholder="Question title"
                placeholderTextColor="#4B667B"
                selectionColor="#4B667B"
                onChangeText={(text) => this.setState({text})}/>

            <View style={styles.listView}>
                <ListView
                    dataSource={dataSource}
                    renderRow={this._renderItem.bind(this)}/>

            </View>
                <TouchableHighlight 
                    onPress={this._addItem.bind(this)}
                    style={styles.buttonView}
                    underlayColor='rgba(0,0,0,0)'>
                    <Text style={styles.buttonText}>
                        Add option
                    </Text>
                </TouchableHighlight>
        </View>


    );
}

}

var styles = StyleSheet.create({ container: { width: 300, flex :1, }, listView: { flex: 1, }, question: { height: 30, fontSize: 20, fontWeight: "100", color: '#4B667B', marginTop: 10, marginBottom: 10, }, buttonView: { width: 300, paddingVertical: 9, borderWidth: 1, borderColor: '#F868AF', marginBottom: 13, }, buttonText: { textAlign: 'center', fontSize: 25, color: '#F868AF', fontWeight: '500' }, });

ListView item: LongButton

'use strict'

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

class LongButton extends Component {

render(){
    return (
        <TouchableHighlight 
            onPress={this.props.onPress}
            style={this.props.btnViewStyle}
            underlayColor='rgba(0,0,0,0)'>
            <Text style={this.props.btnTextStyle}>
                {this.props.text}
            </Text>
        </TouchableHighlight>
    );

} }

module.exports = LongButton;

Xcode warning message upon adding item on alert

app[27881:11151280] the behavior of the UICollectionViewFlowLayout is not defined because: app[27881:11151280] the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values. app[27881:11151280] The relevant UICollectionViewFlowLayout instance is <_UIAlertControllerCollectionViewFlowLayout: 0x7ff0685b1770>, and it is attached to ; layer = ; contentOffset: {0, 0}; contentSize: {0, 0}> collection view layout: <_UIAlertControllerCollectionViewFlowLayout: 0x7ff0685b1770>. 2016-04-06 07:50:01.545 decisionapp[27881:11151280] Make a symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger.

Updates: I tried this but its not working either. Could it be the alert causing these problems? Its just taking forever to render the alert after clicking on the btn.

class SurveyQn extends Component {

constructor(props) { super(props);

   this.state = {
       options: [{option: 'Pizza'}],
       dataSource : new ListView.DataSource({
           rowHasChanged: (row1, row2) => row1 !== row2
       })
   };

}

componentWillMount() { var data = this.state.options; this.state.dataSource.cloneWithRows(data); }

_renderItem(item) { return ( {item.option} ); }

_addItem() { AlertIOS.alert( 'Add new option', null, [ { text: 'Add', onPress: (text) => { var options = this.state.options; options.push({option: text}) this.setState({ options: options}) } }, ], 'plain-text' ); }

render(){ return (

           <View style={styles.listView}>
               <ListView
                   dataSource={this.state.dataSource}
                   renderRow={this._renderItem.bind(this)}/>

           </View>
               <TouchableHighlight 
                   onPress={this._addItem.bind(this)}
                   style={styles.buttonView}
                   underlayColor='rgba(0,0,0,0)'>
                   <Text style={styles.buttonText}>
                       Add option
                   </Text>
               </TouchableHighlight>
       </View>


   );

} }

like image 923
jomaint Avatar asked Nov 08 '22 17:11

jomaint


1 Answers

Before diving into complex EcmaScript notation, you can use simple notation. Here is a simple example of ListView. Please go through it and understand how it works.

var API = require('./API');
module.exports = React.createClass({
  getInitialState: function(){
    return {
      rawData: [],
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2
      }),
      loaded: false,
    }
  },
  componentWillMount: function(){
    this.loadData();
  },
  loadData: function(){
    API.getItems()
    .then((data) => {
      this.setState({
        rawData: this.state.rawData.concat(data),
        dataSource: this.state.dataSource.cloneWithRows(data),
        loaded: true,
      });
    });
  },
  render: function(){
    return(
        <ListView 
          dataSource={this.state.dataSource}
          renderRow={this.renderItem}
          style={styles.listView}>
        </ListView> 
    );
  },
  renderItem: function(item){
    return (
      <View>
          <Text>Custom Item</Text>
      </View>
    );
  },
}

In API.js, I am fetching data from an API.

getItems: function(){
        var REQUEST_URL = 'http://api.example.org/item/get?api_key=xxxx;
        return fetch(REQUEST_URL)
            .then((response) => response.json())
            .then((responseData) => {
                return responseData.results.sort(sortByDate);
            });
    }

The code may not work, since I have not tested. But you can refer my sample project on github. Repo

like image 118
Mihir Avatar answered Nov 14 '22 23:11

Mihir