React Native evaluating 'dataSource.rowIdentities - react-native

I'm making a basic ListView with dataSource in React-Native, with data that I fetch.
class Movies extends Component {
render() {
if (this.state.dataSource.getRowCount() === 0) {
return (
<View style={styles.container}>
<Text>
loading....
</Text>
</View>
);
}
else {
return (
<View style={styles.container}>
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow.bind(this)}
/>
</View>
);
}
}
constructor(props){
super(props);
this.state = {
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
}),
};
}
componentWillMount() {
this.fetchData();
}
fetchData(){
fetch(HOT_MOVIES_URL)
.then((response) => response.json())
.then((responseData) => {
if (responseData) {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(responseData),
});
}
})
.done();
}
}
yet, I get a
undefined is not an object (evaluating 'dataSource.rowIdentities')
error, tried many ways is also not work contain this question, Any ideas?

Try setting up the ListView DataSource as a reusable variable, then reusing it whenever you need it. Also, you may be needing to set the dataSource as an empty array until your data comes in. Try something like this:
var ds = new ListView.DataSource({ rowHasChanged: (row1, row2) => row1 !== row2 })
class Movies extends Component {
render() {
if (this.state.dataSource.getRowCount() === 0) {
return (
<View style={styles.container}>
<Text>
loading....
</Text>
</View>
);
}
else {
return (
<View style={styles.container}>
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow.bind(this)}
/>
</View>
);
}
}
constructor(props){
super(props);
this.state = {
dataSource: ds.cloneWithRows([]),
};
}
componentWillMount() {
this.fetchData();
}
fetchData(){
fetch(HOT_MOVIES_URL)
.then((response) => response.json())
.then((responseData) => {
if (responseData) {
this.setState({
dataSource: ds.cloneWithRows(responseData),
});
}
})
.done();
}
}

This problem seems to be caused by trying to render ListView with a falsy list.
I just opened an app I hadn't used in like 6 months and it exploded fantastically because the database was wiped and this ListView was trying to render and getting an empty list from Redux mapStateToProps.
Long debug story short, I put an empty list check in the render method:
render() {
if (!this.props.employees.length) {
return (
<View>
<Text>NO EMPLOYEES TO LIST</Text>
</View>
)
}
return (
<ListView
enableEmptySections
dataSource={this.dataSource}
renderRow={this.renderRow}
/>
)
}
If you somehow keep getting it after that, put a falsy check in renderRow.

Related

React Native Create one application which will call one API Using thread and store it in some file

I'm new to React Native Would like to get any good solution for following task:
Create one application which will call one API
(https://api.napster.com/v2.0/playlists?apikey=ZTk2YjY4MjMtMDAzYy00MTg4LWE2MjYtZDIzNjJmMmM0YTdm).
Using thread and store it in some file.
Current Code
class App extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: null,
}
}
componentDidMount() {
return fetch('https://api.napster.com/v2.0/playlists?apikey=ZTk2YjY4MjMtMDAzYy00MTg4LWE2MjYtZDIzNjJmMmM0YTdm')
.then(response => response.json())
.then((responseJSON) => {
this.setState({
isLoading: false,
dataSource: responseJSON.playlists,
})
})
.catch((error) => {
console.log(error);
})
}
render() {
if (this.state.isLoading) {
return (
<View style={styles.container}>
<ActivityIndicator />
</View>
)
} else {
let dbSource = this.state.dataSource.map((val, key) => {
return (
<View key={key} style={styles.item}>
<Text>{val.name}</Text>
</View>
)
})
return (
<View style={styles.container}>
{dbSource}
</View>
);
}
}
};

How do you use checkbox in map function in React Native?

My current code is like this.
export default class All extends React.Component {
constructor(props) {
super(props);
this.state = {
items: [],
checkedItems: new Map(),
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(id) {
this.setState((prevState) => ({ checkedItems: prevState.checkedItems.set(id, true) }));
console.log(this.state.checkedItems);
}
async componentDidMount() {
const items = ...;
this.setState({ items });
}
render() {
const { items } = this.state;
return (
<Container>
<Content>
<View>
{items.map((item) => (
<View key={item.id}>
<Text>{item.name}</Text>
<View>
<CheckBox
checked={this.state.checkedItems.get(item.id)}
onPress={() => this.handleChange(item.id)}
/>
</View>
</View>
))}
</View>
</Content>
</Container>
);
}
}
I would like to know how to uncheck.
Also, when I firstly check, console.log() in handleChange() outputs Map {}.
Is it correct?
Or if you know better way bay to use checkbox in map function, plz tell me.
I would appreciate it if you could give me advices.

React Native: Fetch data every 10 clicks on a button

I've just started working with React Native a few days ago and I find myself a bit stuck. I want to display the values one by one from an api with the click of a button. However, how can I do this without fetching the data every single time, but rather every 10 clicks or so? The code I have right now doesn't work the way I want it to and I do understand why - the countData() function is always called anew, therefore the variable i is always stuck at zero and never advances forward. Ideally, I'd like to loop through the first set of values, display them one by one as the button is clicked and then fetch new data (from the same api) after it runs out of values.
export default class ComponentOne extends Component {
constructor(props) {
super(props);
this.state = {
questions: '',
questions2: '',
}
}
fetchData() {
if (this.state.questions == '') {
fetch('my url')
.then((response) => response.json())
.then((responseData) => {
this.setState({
questions: responseData,
});
this.countData();
})
.done();
}
else this.countData();
}
countData() {
for (let i=0; i < this.state.questions.length; i++) {
this.setState({
questions2: this.state.questions[i],
});
}
}
render() {
return (
<View style={styles.container}>
<View style={styles.textStyle}>
<Text style={styles.instructions}>
Welcome! Click the button to generate a question.
</Text>
<TouchableHighlight
onPress={() => this.fetchData()}
style={styles.bigButton}
underlayColor="lightskyblue">
<Text style={styles.bigButtonText}>Hit me</Text>
</TouchableHighlight>
<Text style={styles.question}>{this.state.questions2}</Text>
</View>
</View>
);
}
}
I hope the problem is clear, thanks in advance!
First things first: you should consider not giving you apis url like that.
I didn't test the code in an app but it should work
export default class ComponentOne extends Component {
constructor(props) {
super(props);
this.state = {
questions: [],
question: "",
count: 0,
}
}
componentWillMount() {
this.fetchData();
}
fetchData() {
fetch('YOUR_URL')
.then((response) => response.JSON())
.then((responseJSON) => {
this.setState({questions: responseJSON, count: 0})
})
}
newQuestion() {
if (this.state.questions[count] != null) {
this.setState({
question: this.state.questions[this.state.count],
count: this.state.count + 1,
})
}
else { //make the fetch call once all of your questions has been displayed
this.fetchData();
}
}
render() {
return (
<View style={styles.container}>
<TouchableHighlight onPress={() => this.newQuestion()}>
<Text>Hit me</Text>
</TouchableHighlight>
<Text>{this.state.question}</Text>
</View>
</View>
);
}
}

fetch data from api row counter

By use of the following Code we can read Data from Server:
class SearchPage extends Component {
constructor(props) {
super(props);
var dataSource = new ListView.DataSource({rowHasChanged:(r1,r2) => r1.ruid != r2.guid});
this.state = {
id: 'SearchPage',
searchinpt: this.props.homesearchinpt,
shopid: this.props.shopid,
dataSource: dataSource.cloneWithRows(shopsArray),
isLoading: true
};
}
componentDidMount(){
this.fetchData();
}
fetchData() {
var name = this.state.searchinpt;
var API_URL = 'http://myurl';
var PARAMS = '?name=' + name;
var REQUEST_URL = API_URL + PARAMS;
fetch(REQUEST_URL)
.then((response) => response.json())
.then((responseData) => {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(responseData),
loaded: true,
});
})
.done();
}
renderLoadingView() {
return (
<View style={styles.container}>
<Text>Loading</Text>
</View>
);
}
SearchisEmpty() {
return (
<View style={styles.container}>
<Text style={styles.notfound}>Not Found</Text>
</View>
);
}
SearchnotEmpty(){
return (
<ListView enableEmptySections = {true}
dataSource={this.state.dataSource}
renderRow=
{(shop) =>
<TouchableOpacity
onPress={(shop_id) => this.onSubmitPressed(shop.shop_id)} >
<View style={styles.container} >
<Image
source={{uri: shop.shop_logo}}
style={{width: 50, height: 50}}>
</Image>
<View>
<Text style={styles.shop_name}>{shop.shop_name}</Text>
<Text style={styles.shop_description}>{shop.shop_description}</Text>
</View>
</View>
<Text>{this.state.searchinpt}</Text>
<Text>{this.state.dataSource.getRowCount}</Text>
</TouchableOpacity>
}
style={styles.listView}
/>
);
}
onSubmitPressed(shopd){
this.props.navigator.push({
id: 'Shop',
passProps:{
thisshopid: shopd
}
})
}
render(shopsArray) {
if (!this.state.loaded) {
return this.renderLoadingView();
}else if(this.state.length < 1){
return this.SearchisEmpty();
} else{
return this.SearchnotEmpty();
}
}
}
There isn't any problem for Render.
Now we have some "if" that Whenever there isn't any Data, must show "Not found", But instead of (Not Found) it shows blank page
How can I solve the problem?
this.state.length will always be undefined as this.state is an object, not an array.
I would store the number of rows in the state to be able to control this behaviour. Something like this:
...
fetchData() {
...
fetch(REQUEST_URL)
.then((response) => response.json())
.then((responseData) => {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(responseData),
loaded: true,
numRows: responseData.length
});
})
.done();
}
...
render(shopsArray) {
if (!this.state.loaded) {
return this.renderLoadingView();
}else if(this.state.numRows < 1){
return this.SearchisEmpty();
} else{
return this.SearchnotEmpty();
}
}

undefined is not an object(evaluating 'this.onSubmitPressed.bind')

I have a listview that shows data through Json. I introduced a function and while clicking on every Row, That shows an Alert including {shop_name}.
But at first step it dosen't recognise the Function.
Function is in the same class
When I put Alert in the onPress, it works
class SearchPage extends Component {
constructor(props) {
super(props);
var dataSource = new ListView.DataSource({rowHasChanged:(r1,r2) => r1.ruid != r2.guid});
this.state = {
id: 'SearchPage',
shopid: this.props.shopid,
homesearchinpt: this.props.homesearchinpt,
dataSource: dataSource.cloneWithRows(shopsArray),
isLoading: true
};
}
componentDidMount(){
this.fetchData();
}
onSubmitPressed(){
Alert.alert(
'Alert Title',
'alertMessage',
)
}
fetchData() {
fetch(REQUEST_URL)
.then((response) => response.json())
.then((responseData) => {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(responseData),
loaded: true,
});
})
.done();
}
render() {
if (!this.state.loaded) {
return this.renderLoadingView();
}
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderShops}
style={styles.listView}
/>
);
}
renderLoadingView() {
return (
<View style={styles.container}>
<Text>Loading</Text>
</View>
);
}
renderShops(shop) {
return (
<View style={styles.container} >
<TouchableOpacity onPress={this.onSubmitPressed.bind(this)}>
<Image
source={{uri: shop.shop_logo}}
style={{width: 50, height: 50}}>
</Image>
<View>
<Text style={styles.shop_name}>{shop.shop_name}</Text>
<Text style={styles.shop_description}>{shop.shop_description}</Text>
</View>
</TouchableOpacity>
</View>
);
}
};
Error:
undefined is not an object(evaluating 'this.onSubmitPressed.bind')
onSubmitPressed(shopName) {
Alert.alert(
'Alert Title',
shopName,
)
}
<TouchableOpacity onPress={() => this.onSubmitPressed(shop.shop_name)}>
I rewrote the Codes and the problem solved.
Thanks