componentDidUpdate() will not be invoked if shouldComponentUpdate() returns false.

componentWillUnmount()

Also, I found for whatever reason, in ES6 + React v15.3.1 (latest) the automatic binding doesn't occur (I thought it was supposed to) as it does in ES5 (same version of React), so I just stored a reference to the bound function, and reused it.


import React from "react";

export default class HeaderMain extends React.Component {

  boundFunc = this.handleResize.bind(this);

  constructor()
  {
    super();

    this.state = {height:window.innerHeight + "px"};
  }

  handleResize(e)
  {
    this.setState({height:window.innerHeight + "px"});
  }

  componentDidMount()
  {
     window.addEventListener('resize', this.boundFunc);
  }

  componentWillUnmount()
  {
    window.removeEventListener('resize', this.boundFunc);
  }

  render() {

    return (
      <header class="header_main" style={{height:this.state.height}}>
         Example Header
      </header>
    );
  }
}

After looking through the auth0 Lock source I found the hide method which has solved my problem:

In my Login component I override the componentWillUnmount method, get a reference to the Auth0Lock, and call hide():


hide() {
  closeLock(this.id, true);
}


componentWillUnmount() {
  this.lock.hide();
}

The first will be started on instance initialisation and the second in componentDidMount(). But the second will override the reference to the first interval which will then not be removed in componentWillUnmount(). You should set your interval only in componentDidMount() and init it with null:


export default class ChatBox extends Component<ChatBoxProps, ChatBoxState> {
    interval = null;

    componentDidMount () {
        this.interval = setInterval(() => this.fetchComments(), 500);
        /* ... */
    }

    componentWillUnmount () {
        clearInterval(this.interval);
    }

    /* ... */
}

Instead, save the function in your constructor and use that reference:


class NavBar extends Component {
  constructor() {
    super();

    this.state = {
      distanceScrolled: null
    }

    this.scrollFn = this.handleScroll.bind(this);
  }

  componentDidMount() {
    window.addEventListener('scroll', this.scrollFn);
  }

  componentWillUnmount() {
    window.removeEventListener('scroll', this.scrollFn);
  }

  handleScroll(e){
    const distanceScrolled = e.srcElement.body.scrollTop;

    this.setState({ distanceScrolled: distanceScrolled });
  }

  render { ... } 
}

It doesn't fire because the component remains mounted. With respect to reconciliation, the conditional expression

is indistinguishable from

since both clauses refer to the same ChildFlipped component. If you add keys, you can make them distinguishable and trigger unmounting:


this.state.clickCounter % 2
? <ChildFlipped name={"Even"} numberOfClicks={this.state.clickCounter}/>
: <ChildFlipped name={"Odd"} numberOfClicks={this.state.clickCounter}/>


<ChildFlipped name={this.state.clickCounter % 2? "Even" : "Odd"} 
              numberOfClicks={this.state.clickCounter}/>


his.state.clickCounter % 2
? <ChildFlipped key='even' name={"Even"} numberOfClicks={this.state.clickCounter}/>
: <ChildFlipped key='odd' name={"Odd"} numberOfClicks={this.state.clickCounter}/>

You need to cancel any timeouts you have running in componentWillUnmount. Store a reference to them and delete them.


class Form extends React.Component {
    constructor(props, context) {
        this.state = {resend: false};
        this.timeouts = [];
    }

    componentWillUnmount(props, context) {
        this.timeouts.forEach(t => window.clearTimeout(t));
    }

    componentDidMount() {
        const max = 3;

        if (this.props.count < max) {
            const timeoutId = setTimeout(() => {
                this.setState({resend: true});
            }, 1000);
            this.timeouts.push(timeoutId);
        }
    }

    render() {
        return (
            <form>
                ...
                {this.state.resend ? <Component/> : null}
            </form>
        );
    }
}

You need to set it up so you create the firebase reference when the component is being constructed. I think something like this should work. I've added comments to explain what I've done:


class MySuperAwesomeClass extends React.Component {
  // this will be a fixed reference you can use to attach/detach the listener
  firebaseRef;

  constructor(props) {
    super(props);

    // assign a reference to this component's firebaseRef member
    this.firebaseRef = Firebase.database().ref(
      `/UserToQuestion/${Firebase.auth().currentUser.uid}`
    );

    // grab the data from the server and call this.onFirebaseValueChanged every time it changes
    this.firebaseRef.orderByChild("Question").on("value", this.onFirebaseValueChanged);
  }

  componentWillUnmount() {
    // detach all listeners to this reference when component unmounts (very important!)
    this.firebaseRef.off();
  }

  onFirebaseValueChanged = snapshot => {
    console.log("-----------");
    // I created these arrays because they didn't seem to exist
    const titlesArray = [];
    const contentArray = [];
    const dataArray = [];

    // use let instead of var because it's changing
    let i = 0;
    snapshot.forEach(childSnapshot => {
      // use const instead of var
      const childData = childSnapshot.val();

      titlesArray.push(childData.Title);
      contentArray.push(childData.Question);
      dataArray.push({title: titlesArray[i], content: contentArray[i]});
      i++;
      console.log(titlesArray);
    });
  };

  render() {
    return <Text>Render method shouldn't be talking to the server!</Text>;
  }
}

Here I am adding another class where I have made use of my network class defined above, actually its a component in React world so inside render method we have added this component and got reference of that component upon which we are calling a method callWebService()


import React, { Component } from 'react';

import {  StyleSheet, Text, View, Button,Switch, Alert, Image, TouchableHighlight, Dimensions, Platform,AppState } from 'react-native';
import Constants from '.././utilities/Constants'
import {Screens} from '.././navigation/Screens'
import {ScreenClass} from '.././navigation/Screens';
import TextInputCustom from '.././components/TextInputCustom';
import {SessionManager} from '../utilities/SessionManager';
import {WebServiceCallManager} from '.././WebServiceCallManager';
import {NavigationManager} from '.././navigation/NavigationManager';
import Fingerprint from '.././fingerprint/FingerprintAndroid';


const dismissKeyboard = require('dismissKeyboard');
const { width, height } = Dimensions.get("window");
let opacity = 1;
// source address of login background image
const loginBackgroundViewImg = require('.././assets/login_box.png');
const biometricImage = require('.././assets/biometric_icon.png');

var langs = new Constants(); // language localization


/* Login View for displaying TextInputs(username, passwords),
   Buttons (Login, Register) and Labels (Terms & condition , forget password)
*/

export class LoginContainer extends Component {
     constructor(props){
          super(props);
          this.state = {
            username: '' , // user33
            password: '', // Awaqas@2
            emptyInputFields : '',
            falseSwitchIsOn : true,
            phase: 'normal',
            message: '',
            cancelled: false
          }
     }



     componentDidMount() {
      //  Fingerprint.saveCredentials("user33","Awaqas@2",()=>{
      //   this.setState({
      //       phase: 'saved',
      //       message: ''
      //   });
      //  },()=>{});

            this.authenticate();

             AppState.addEventListener("change", async(state) => {
                 try {
                     if(state === "active" && await Fingerprint.isAuthenticationCanceled()) {
                         this.authenticate()
                     }
                 }
                 catch(z) {
                     console.error(z)
                 }
             })
         }

         async componentWillUnmount() {
             try {
                 if(!Fingerprint.isAuthenticationCanceled()) {
                     //stop listening to authentication.
                     await Fingerprint.cancelAuthentication();
                 }
             } catch(z) {
                 console.error(z);
             }
         }

         async authenticate() {

             try {
                 // do sanity checks before starting authentication flow.
                 // HIGHLY recommended in real life usage. see more on why you should do this in the readme.md
                 const hardware = await Fingerprint.isHardwareDetected();
                 const permission = await Fingerprint.hasPermission();
                 const enrolled = await Fingerprint.hasEnrolledFingerprints();

                 if (!hardware || !permission || !enrolled) {
                     let message = !enrolled ? 'No fingerprints registered.' : !hardware ? 'This device doesn\'t support fingerprint scanning.' : 'App has no permission.'
                     this.setState({
                         phase: 'fail',
                         message
                     });
                     return;
                 }

                  await Fingerprint.authenticate(warning => {
                     this.setState({
                         phase: 'warn',
                         message: warning.message
                     })
                 });

                 // if we got this far, it means the authentication succeeded.
                 this.setState({
                     phase: 'success',
                     message: ''
                 });

                 // in real life, we'd probably do something here (process the payment, unlock the vault, whatever)
                 // but this is a demo. so restart authentication.
                // setTimeout(() => this.authenticate(), 3000);

             } catch (error) {
                 if(error.code == Fingerprint.FINGERPRINT_ERROR_CANCELED) {
                     // we don't show this error to the user.
                     // we will check if the auth was cancelled & restart the flow when the appstate becomes active again.
                     return;
                 }
                 this.setState({
                     phase: 'fail',
                     message: error.message
                 })
             }
         }

      buttonsHandler(type){
          switch (type) {
               case 'forgotpassword':
                    this.props.navigation.push(Screens.ForgotPasswordScreen);
                    break;
               case 'forgotuserid':
                this.props.navigation.push(Screens.ForgotUserIDScreen);
                    break;
               case 'unlockprofile':
                this.props.navigation.push(Screens.UnlockProfileScreen);
                    break;
              case 'register':
                  dismissKeyboard();
                  this.props.navigation.push(Screens.RegistrationWelcomeScreen);
                  break;
               case 'login':
                    this.loginWebServiceCall();
                    break;
               default:
                     alert(type + ' is pressed');

          }
    }


    // this will be called when user hit login button

    loginWebServiceCall()
    {

         if(this.state.username.length === 0 &&  this.state.password.length === 0){
            this.setState({emptyInputFields:langs.strings.login_userid_password_empty});
            this.userName.textFocus();
         }
         else if (this.state.username.length === 0 ) {
           this.setState({emptyInputFields:langs.strings.login_userid_empty});
           this.userName.textFocus();
         }
         else if ( this.state.password.length === 0) {
           this.setState({emptyInputFields:langs.strings.login_password_empty});
           this.password.textFocus();

         }else{
              this.setState({emptyInputFields:''});
              var params = {
                   "Password": this.state.password,
                   "UserName": this.state.username,
                   "LoginType": 'Manual',
              };

              this.webservicemanager.callWebService("LOGIN","TRANSACTION",params,(response) => {this.handleWebServiceCallResponse(response);});
         }
    }

    /* handle the web service successfull response error
    response will be handled inside WebServiceCallManager */

    handleWebServiceCallResponse(data){

        dismissKeyboard();

        var userData = {
            "username":this.state.username,
            "password":this.state.password
        }
        var passwordPolicy = {
          "passwordPolicy" : data.Body.Transaction.PasswordPolicy,
          "passwordPolicyRegex" : data.Body.Transaction.PasswordPolicyRegex
        }

        SessionManager.setSessionValue(Constants.FASTTRANSFER_BENEFICIARY_BRANCH_LIST,data.Body.Transaction.BranchList);
        SessionManager.setSessionValue(Constants.BENEFICIARY_COUNTRY,data.Body.Transaction.CountryList);
        SessionManager.setSessionValue(Constants.BENEFICIARY_RELATIONSHIP, data.Body.Transaction.RelationList);
        SessionManager.setSessionValue(Constants.LOGIN_USERDATA, userData);
        SessionManager.setSessionValue(Constants.CUSTOMER_NUMBER,data.Body.Transaction.CUSTNO);
        SessionManager.setSessionValue(Constants.PASSWORD_POLICY, passwordPolicy);
        SessionManager.setSessionValue(Constants.SECURITY_QUESTIONS_LIST,data.Body.Transaction.Questions);
        var nextScreenName = data.Body.Transaction.NextScreenName;

        const SpecificScreenClass = ScreenClass.getClassFromClassName(nextScreenName);
        SessionManager.setSessionValue('nextScreenName', nextScreenName);
        this.props.navigation.push(SpecificScreenClass);


        this.setState({
             username:'',
             password:'',
             emptyInputFields:''
        });
        this.userName.textClear();
        this.password.textClear();
        dismissKeyboard();

    }

    // handling text input field focus
   textHandler(){
     this.password.focus();
   }

   onSwitchToggle(value){
     if(value){
        opacity = 1;
      }
     else{
       opacity= 0.4;
     }
     this.setState({falseSwitchIsOn: value});
   }

     render(){
       this.fetchCredentials(this.webservicemanager,this.handleWebServiceCallResponse.bind(this));

          return(
               <View style={ styles.loginView}>
                 <Image style={ styles.loginViewBackground} source={loginBackgroundViewImg}>


                 <View>

                   <TextInputCustom
                        ref ={(ref) => this.userName = ref}
                        placeholder={langs.strings.login_userid_placeholder}
                        secureTextEntry={false}
                        onChangeTextCallback={val => this.setState({'username' : val})}
                        returnKeyType="next"
                        textInputWidth = {((width*86)/100)}
                        // onEndEditingCallback = {() => this.password.textFocus()}
                   />

                   <TextInputCustom
                        ref ={(ref) => this.password =ref}
                        placeholder={langs.strings.login_password_placeholder}
                        secureTextEntry={true}
                        onChangeTextCallback={val => this.setState({'password' : val})}
                        returnKeyType="done"
                        textInputWidth = {((width*86)/100)}
                   />
                   <Text style={ styles.emptyInputFields}>{this.state.emptyInputFields}</Text>
                 </View>
                 <View style={ styles.middleContainerViewButtons}>
                   <View style={ styles.middleContainerViewButtonsBtn}>
                     <TouchableHighlight onPress={ () => this.buttonsHandler('login')}>
                       <Text style={ styles.btnTextLabels}>{langs.strings.login_btnLogin}</Text>
                     </TouchableHighlight>
                   </View>
                   <View style={ styles.middleContainerViewButtonsBtn}>
                     <TouchableHighlight onPress={() => this.buttonsHandler('register')}>
                       <Text style={ styles.btnTextLabels}>{langs.strings.login_btnRegister}</Text>
                     </TouchableHighlight>
                   </View>
                 </View>
                 <TouchableHighlight onPress={() => {this.buttonsHandler('forgotpassword')}} underlayColor = {'transparent'}>
                   <Text style={ styles.labels} >
                     Forogot Password
                   </Text>
                 </TouchableHighlight>
                 <TouchableHighlight onPress={() => {this.buttonsHandler('forgotuserid')}} underlayColor = {'transparent'}>
                   <Text style={ styles.labels} >
                     Forogot User ID
                   </Text>
                 </TouchableHighlight>
                 <TouchableHighlight onPress={() => this.buttonsHandler('terms')} underlayColor = {'transparent'}>
                   <View >
                     <Text style={ styles.labels}>
                       {langs.strings.login_txtTermsAndConditions}
                     </Text>
                   </View>
                 </TouchableHighlight>
                 <View style={styles.fingerPrintLayout}>
                 <TouchableHighlight  underlayColor = {'transparent'}>
                   <View >
                     <Image style={styles.biometricImage} source={biometricImage}/>
                   </View>
                 </TouchableHighlight>
                   <View style={styles.switchRow} >
                   <Text style={ styles.labels} >
                     Enable Finger Print Login
                   </Text>
                     <Switch
                     onValueChange={(value) => this.onSwitchToggle(value) }
                     style={styles.switchControl}
                     value={this.state.falseSwitchIsOn} />
                   </View>
                   <Text>{this.state.message}</Text>
                 </View>

               </Image>
               <WebServiceCallManager visible={false} nav = {this.props.navigation} ref={ (input) => {this.webservicemanager = input;}}/>
             </View>
          );
     }

      fetchCredentials(web,resHandler) {
       if(this.state.phase === 'success') {
        Fingerprint.fetchCredentials(
          (...res) => {
              console.log(res);
              var params = {
                  "Password": res[1],
                  "UserName": res[0],
                  "LoginType": 'Biometric'
             };
             this.setState({username:params.UserName,password:params.Password,phase:''})
             this.webservicemanager.callWebService("LOGIN","TRANSACTION",params,(response) => {this.handleWebServiceCallResponse(response);},
             (err)=> {
             this.authenticate();});
            },
            (res) => {
                console.log(res);
                return null;
              }
        );
     }
   }

} // end of class

Doing a refactoring of UsersChart by mapping the status of both the library and the component, I was able to get rid of all the warnings:


import React, { Component } from 'react';
import PropTypes from 'prop-types';

class UsersCharts extends Component {
    constructor(props) {
        super(props);

        this._isMounted = false;
        this.state = {
            ready: false,
        };
    }

    componentDidMount() {
        this._isMounted = true;
        window.gapi.analytics.ready(() => {
            console.log('Ready to do fireworks');
            if (this._isMounted) {
                 this.setState({ ready: true });
            }
        });
    }

    componentWillUnmount() {
        this._isMounted = false;
    }

    render() {
        const { token } = this.props;

       if (this.state.ready) {
        /**  auth and draw chart */

        this.chart.execute();
       }

       return <div id="chart-container" />;
   }
}

Recommend

React.Component Reference componentDidUpdate()

React.Component Reference componentDidMount()

React.Component Reference constructor()

React.Component Reference render()

React.Component Overview

Render Props Caveats Be careful when using Render Props with React.PureComponent

React Render Props Using Props Other Than render

React Render Props Use Render Props for Cross-Cutting Concerns

React Render Props

React Hooks FAQ Performance Optimizations How to read an often-changing value from useCallback?

React Hooks FAQ Performance Optimizations How to avoid passing callbacks down?

React Hooks FAQ Performance Optimizations Are Hooks slow because of creating functions in render?

React Hooks FAQ Performance Optimizations How to create expensive objects lazily?

React Hooks FAQ Performance Optimizations How to memoize calculations?

React Hooks FAQ Performance Optimizations How do I implement shouldComponentUpdate?

React Hooks FAQ Performance Optimizations What can I do if my effect dependencies change too often?

React Hooks FAQ Performance Optimizations Is it safe to omit functions from the list of dependencies?

React Hooks FAQ From Classes to Hooks How can I measure a DOM node?

React Hooks FAQ From Classes to Hooks Is there something like forceUpdate?

React Hooks FAQ From Classes to Hooks How do I implement getDerivedStateFromProps?

React Hooks FAQ From Classes to Hooks Why am I seeing stale props or state inside my function?

React Hooks FAQ From Classes to Hooks How to get the previous props or state?

React Hooks FAQ From Classes to Hooks Should I use one or many state variables?

React Hooks FAQ From Classes to Hooks Is there something like instance variables?

React Hooks FAQ Adoption Strategy How to test components that use Hooks?

React Forms Controlled Input Null Value

React Forms Handling Multiple Inputs

React Forms The file input Tag

React Forms The select Tag

React Forms The textarea Tag

React Forms Controlled Components

React Forms

Thinking in React Start With A Mock

React Typechecking With PropTypes Function Components

React Typechecking With PropTypes Default Prop Values

React Typechecking With PropTypes Requiring Single Child

React Typechecking With PropTypes PropTypes

React Typechecking With PropTypes

React Lifting State Up Lifting State Up

React Lifting State Up Writing Conversion Functions

React Lifting State Up Adding a Second Input

React Lifting State Up

ReactDOM Reference createPortal()

ReactDOM Reference findDOMNode()

ReactDOM Reference unmountComponentAtNode()

ReactDOM Reference hydrate()

ReactDOM Reference render()

React Release Channels Next Channel Using the Next Channel for Integration Testing

React Uncontrolled Components The file input Tag