leecade / leecade/react-native-swiper

onIndexChanged is not triggered if state is set after fetch

Open
#701 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
10.5k
Forks
2.3k
PR merge metrics
No merged PRs in 30d

Description

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

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the Android example with react-native-swiper 1.5.13 and React Native 0.51, starting from TestSwiper's componentDidMount, fetch callback, and render method. Inspect how the Swiper component handles children when dataMovies changes after the fetch. Done means onIndexChanged fires when the fetched movie slides are swiped, while the existing direct-state example continues to work.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, react-native
Domain
mobile
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.