react-native-swiper
react-native-swiper copied to clipboard
onIndexChanged is not triggered if state is set after fetch
Which OS ?
Android
Version
Which versions are you using:
- react-native-swiper v? 1.5.13
- react-native v0.?.? 0.51
Expected behaviour
When data is fetched from remote network, onIndexChanged to work.
Actual behaviour
onIndexChanged is not triggered
Steps to reproduce
Below is a sample screen code.
import React, { Component } from "react";
import {
View,
Text,
ImageBackground,
StyleSheet,
Dimensions
} from "react-native";
import Swiper from "react-native-swiper";
export default class TestSwiper extends Component {
constructor(props) {
super(props);
this.state = {
dataMovies: []
};
}
componentDidMount() {
this.getJsonData().then(dataMovies => {
this.setState({
dataMovies: dataMovies
});
});
}
getJsonData = () => {
return new Promise((resolve, reject) => {
fetch("https://facebook.github.io/react-native/movies.json")
.then(response => response.json())
.then(responseJson => {
resolve(responseJson.movies);
})
.catch(error => {
console.error(error);
});
});
};
swiperIndexChanged = index => {
console.log("swiperIndexChanged", "index", index);
};
onScrollEnd = (e, state) => {
console.log("Index is:", state.index);
};
renderMovie = () => {
let movieView: any;
movieView = this.state.dataMovies.map((item, key) => {
return (
<View key={key}>
<Text>{item.title}</Text>
</View>
);
});
return movieView;
};
render() {
return [
<View style={{ flex: 1, justifyContent: "space-between" }} key="mainView">
<Swiper
loadMinimal={false}
style={{ flex: 1, justifyContent: "space-between" }}
onIndexChanged={index => {
console.log("onindexchanged");
this.swiperIndexChanged(index);
}}
loop={false}
showButtons={true}
onMomentumScrollEnd={this.onScrollEnd}
>
{this.renderMovie()}
</Swiper>
</View>
];
}
}
Swiper functions correctly but onIndexChanged is not triggered.
If we change the componentDidMount function as follow, and just set the "dataMovies" state directly, the onIndexChanged is triggered.
componentDidMount() {
this.setState({
dataMovies: MoviesData.movies
});
}
I am not sure if this is caused by swiper or it is something about setting the state after the fetch call.
Any comments on what could be cause of index change not working in the first case
Thank you
Not sure why swiper functioned as it should except the onIndexChanged but it works when you postpone the rendering till the data is ready.
Working code is below if anyone else experience the same problem.
import React, { Component } from "react";
import {
View,
Text,
ImageBackground,
StyleSheet,
Dimensions
} from "react-native";
import Swiper from "react-native-swiper";
import MoviesData from "./movies.json";
export default class TestSwiper extends Component {
constructor(props) {
super(props);
this.state = {
dataMovies: [],
loadData: false
};
}
componentDidMount() {
/* this.setState({
dataMovies: MoviesData.movies
});
*/
this.getJsonData().then(dataMovies => {
/*this.setState({
dataMovies: dataMovies
});*/
});
}
getJsonData = () => {
return new Promise((resolve, reject) => {
fetch("https://facebook.github.io/react-native/movies.json")
.then(response => response.json())
.then(responseJson => {
this.setState({
dataMovies: responseJson.movies,
loadData: true
});
resolve(responseJson.movies);
})
.catch(error => {
console.error(error);
});
});
};
swiperIndexChanged = index => {
console.log("swiperIndexChanged", "index", index);
};
onScrollEnd = (e, state) => {
console.log("Index is:", state.index);
};
renderMovie = () => {
let movieView: any;
movieView = this.state.dataMovies.map((item, key) => {
return (
<View key={key}>
<Text>{item.title}</Text>
</View>
);
});
return movieView;
};
renderLoadingView() {
return (
<View>
<Text>Loading . . .</Text>
</View>
);
}
render() {
if (this.state.loadData) {
return [
<View
style={{ flex: 1, justifyContent: "space-between" }}
key="mainView"
>
<Swiper
loadMinimal={false}
style={{ flex: 1, justifyContent: "space-between" }}
onIndexChanged={index => {
console.log("onindexchanged");
this.swiperIndexChanged(index);
}}
loop={false}
showButtons={true}
onMomentumScrollEnd={this.onScrollEnd}
>
{this.renderMovie()}
</Swiper>
</View>
];
} else {
return this.renderLoadingView();
}
}
}
I also am experiencing this issue (I understand it may be expected behaviour) and the workaround is to render Swiper after list data is ready. Am curious to see what would happen if data was appended to list afterwards...
@ozmaat your solution worked for me ...waiting for loading data!!!...?TNX a lot
Thanks Bro!!!!
u can try this way
Swiper key={this.state.banners.length} /Swiper
@narcissus571 it works for me, but I still don't understand why
@narcissus571 it works. amazing