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> );
} }
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With