reactjsreact-nativeswiper.jsreact-native-swiper

How to properly update a react native swiper component when state changes?


I have a react native component that uses react-native-swiper module. One of the slides in the swiper contains text which is set in the component's state. In the component I also have a modal with form that changes the state's text when user tries to save the input data from the modal.

The question is: in my current implementation, every time I saves a new data, the swiper gets dragged to the last slide, and re-render the slides (the process is laggy). So I wonder what's the best way to update the slides more smoothly?

Below is my component:

'use strict';

import React from 'react';
import { 
  Dimensions, 
  StyleSheet, 
  View, 
  Text, 
  ScrollView,
  AlertIOS,
  AsyncStorage
} from 'react-native';
import { StackNavigator } from 'react-navigation';
import Swiper from 'react-native-swiper';
import Button from 'react-native-button';
import { saveName, getName } from '../Utils/dataService';
import { showAlert } from '../Utils/alert';
import HeaderSection from './HeaderSection';
import { styles } from '../Styles/Styles';
import { renderPagination } from './renderPagination';

class MainView extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: '',
      currIndex: 0
    };
  }

  componentDidMount() {
    getName(val => this.setState({'name': val}));
  }

  showInputModal() {
    AlertIOS.prompt(
      'Enter New Doctor Name', null,
      [
        {
          text: 'Save',
          onPress: name => saveName(name, val => this.setState({'name': val}))
        },
        { text: 'Cancel', style: 'cancel' }
      ]
    );
  }

  render() {
    return (
      <View style={{flex: 1}}>
        <Swiper ref='swiper' onIndexChanged={(index) => this.setState({'currIndex': index})}>
          <View style={styles.slide}>
            <Text style={styles.text}>Hello {this.state.name}</Text>
          </View>
        </Swiper>
        <Button onPress={this.showInputModal.bind(this)}>
          Customize
        </Button>
      </View>
    );
  }
}

export default MainView;

Solution

  • I had the similar problem. Then I tried rendering the Swiper (in your case) from the state and it optimizes the performance. I hope it will solve your problem too.

    Just replace your class MainView with this one:

    class MainView extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                name: '',
                currIndex: 0,
                swiper: this.renderSwpier
            };
        }
    
        componentDidMount() {
            getName(val => this.setState({'name': val}));
        }
    
        renderSwpier(){
            return(
                <Swiper ref='swiper' onIndexChanged={(index) => this.setState({'currIndex': index})}>
                    <View style={styles.slide}>
                        <Text style={styles.text}>Hello {this.state.name}</Text>
                    </View>
                </Swiper>
            )
        }
    
        showInputModal() {
            AlertIOS.prompt(
                'Enter New Doctor Name', null,
                [
                    {
                        text: 'Save',
                        onPress: name => saveName(name, val => this.setState({'name': val}))
                    },
                    { text: 'Cancel', style: 'cancel' }
                ]
            );
        }
    
        render() {
    
            return (
                <View style={{flex: 1}}>
                    {this.state.swiper.call(this)}
                    <Button onPress={this.showInputModal.bind(this)}>
                        Customize
                    </Button>
                </View>
            );
        }
    }