Search code examples
react-nativethissetstate

React Native - How to set state of variable contained in the imported js file


I have created a Loader.js to show ActivityIndicator in a Modal. I include Loader.js in my all pages and show it when page is processing / rendering.

Loader.js

const Loader = props => {
  const {
    loading,
    ...attributes
  } = props;

  return (
    <Modal
      transparent={true}
      animationType={'slide'}
      visible={ loading }
                   onRequestClose={() => { this.setState({loading: false})}}>
      <View style={styles.modalBackground}>
        <View style={styles.activityIndicatorWrapper}>
          <ActivityIndicator
            animating={loading} />
        </View>
      </View>
    </Modal>
  )
}

export default Loader;

In the screen where I am including Loader.js I have defined loading state variable and to show loader I do this.setState({loading: true});

And in render of the screen I have added:

      <Loader
          loading={this.state.loading} /> 

But sometimes the Loader hangs. I want to add a Close button in the Modal (Loader.js) to provide a way to the User to cancel Loader. But I am not able to set the state of loading to false inside Loader.js. I get error: _this.setState is not a function.

Please can anyone suggest how can I achieve closing the Loader? I do not want to modify the screens where Loader.js is being included as that would require changing multiple screens.

Any help is much appreciated. Thank you.


Solution

  • Simple create a pure component like below :

    Loader.js

    import {ActivityIndicator, Modal, Text, View} from "react-native";
    import React, {PureComponent} from 'react';
    
    
    class Loader extends PureComponent {
    
    static propTypes = {
            onCancel: PropTypes.func,
            isLoading : PropTypes.bool
        };
    
    
        render() {
            return <Modal
                animated={true}
                visible={this.props.isLoading}
                transparent={true}
                animationType={'fade'}>
    
                <View style={{justifyContent: 'center', alignItems: 'center', flex: 1}}>
    
                    <View style={{
                        width: 120, height: 40, borderRadius: 5, padding: 10, backgroundColor: 'lightcoral',
                        justifyContent: 'center', alignItems: 'center', flexDirection: 'row'
                    }}>
    
                        <ActivityIndicator
                            color='white'
                            size={'small'}
                            animating={true}/>
    
                        <Text style={{padding: 8, color: 'white'}}>Loading</Text>
    
                    </View>
    
                    <Button title={'Cancel'} onPress={this.props.onCancel}/>
    
                </View>
    
            </Modal>;
        }
    
    
    }
    
    export default Loader
    

    Import that file and use loader in any .js using below command :

    import Loader from "./source/Loader";
      <Loader isLoading={this.state.isLoading} onCancel={this._cancelProgress}/>
    

    To manully handle cancel functionality you have to use callback function.

    you have to define cancelProgress method in your .js file to change the state and pass it to loader.js file same as above example.

    _cancelProgress = () => {
            this.setState({
                isLoading: false
            });
        }
    

    Change the state of isLoading to true/false to show and hide the ActivityIndicator.

    this.setState({isLoading: false})