Search code examples
reactjsreact-nativeredux-saga

Otp Verification only the time when user install app first time in react native with saga


I am checking user is valid or not after displaying splash screen. So In my splash screen I checked the data from redux saga like below


  Hide_Splash_Screen=()=>{
    this.setState({
      isVisible:false   
    })
    if(this.props.phoneNumberData !== null )
    {
      this.props.navigation.navigate('HomeScreen')
    }

    else
    {
      this.props.navigation.navigate('PhoneVerification')
    }
  } 
  
  
  
  componentDidMount(){
    setTimeout(()=>{  
      this.Hide_Splash_Screen();  
    }, 2000);
   
    this.props.fetchSavePhoneNumber()

  }

So if the user has install the app for firstime then PhoneVerification Screen is prompted and not it will directly go into HomeScreen

So here is my logic to check phone verification with otp and then store as a new user in saga

handleSendCode=()=>{
        var phoneno = '+91'+this.state.phone
        firebase
            .auth()
            .signInWithPhoneNumber(phoneno)
            .then(confirmResult => {
                this.setState({ confirmResult })
            })
            .catch(error => {
                alert(error.message)
                console.log(error)
            })
        this.setState({showotpScreen:true})    
    }
 checkOtp=()=>{
        this.state.confirmResult
            .confirm(this.state.otp)
            .then(user => {
                this.props.NewPhoneNumber(user)
                this.props.navigation.navigate('HomeScreen')
            })
            .catch(error => {
                alert(error.message)
                console.log(error)
            })
          
    }

For ReduxSaga implementation I take two different action and one reducer like this

phoneaction

export const fetchSavePhoneNumber = () => ({
    type: 'FETCH_SAVE_PHONENUMBER',
});

export const NewPhoneNumber = (data) => ({
    type:'SAVE_NEW_PHONENUMBER',
    payload: data
});

phoneReducer

const initialState = {
    phoneNumberData: null,
};

export default (state = initialState, { type, payload }) => {
    switch(type){
        case 'SAVE_NEW_PHONENUMBER':
            return{
                ...state,
                phoneNumberData: payload,
            };
        case 'IS_VALIDATING':
            return{
                ...state,
            };  
        default:
            return state;         
    };
}

And my Two Saga will look like this

NewPhoneNumber


import { call, put, select, takeLatest } from 'redux-saga/effects';
import AsyncStorage from '@react-native-community/async-storage';

const phoneno = state => state.phone.phoneNumberData ;


function* PhoneVerifyTask(action){
    const phoneNumberData = yield select(phoneno);
    
    try{
        
        yield call(AsyncStorage.setItem,'phoneVerify',JSON.stringify(phoneNumberData));
        yield put({ type: 'SAVE_NEW_PHONENUMBER', payload: phoneNumberData });
        
    }
    catch(error){
        console.log(error)
    }

}

function* NewPhoneNumber(){
    yield takeLatest('SAVE_NEW_PHONENUMBER',PhoneVerifyTask)
} 

export default NewPhoneNumber;

FetchSavePhoneNumber

import { call, put, takeLatest } from 'redux-saga/effects';
import AsyncStorage from '@react-native-community/async-storage';

function* fetchVerifyPhoneNumber(action){
    yield put({
        type: 'IS_VALIDATING',
      });
    try
    {
        const response = yield call(AsyncStorage.getItem,'phoneVerify')
        yield put({
            type: 'SAVE_NEW_PHONENUMBER',
            payload: JSON.parse(response) || null
        });
        
    }
    catch(error){
        console.log(e);
        yield put({
            type: 'SAVE_NEW_PHONENUMBER',
            payload: {
              phoneNumberData: null
            },
          });
        
    }
}

function* FetchSavePhoneNumber(){
    yield takeLatest('FETCH_SAVE_PHONENUMBER',fetchVerifyPhoneNumber)
}

export default FetchSavePhoneNumber;

But after successfully storing newPhoneNumberdata and fetchingExisting PhoneNumberdata my whole redux act as a infinite loop


Solution

  • This is probably because your component that calls FETCH_... is re-rendered and calls fetch another time.

    I'd suggest either calling the action higher up in your app (in your App.js constructor maybe). You can also fire sagas once on app load in your generator directly.