Search code examples
javascriptreact-nativeasyncstorage

How to pass parameter from AsyncStorage to function React Native


I have a login page. There, the user enters data and submits to the API. The API gives an answer that there is such a user and gives him an id from the database. I write this id in storage. Next, the user is taken to the home page. There is a component that is responsible for getting the username (and indeed all other data) the essence of the component: 1 The parameter receives an id and forms it into a json request. 2 The parameter sends this request to the API and receives the user's data in the response (if the id matches) 3) return which draws the interface and gives the user data from the API response

Problem: When changing an account (or re-logging in), it gives a json request error (in fact, the API does not accept an empty request, so it rejects it) The point of getting an ID is 100%. When the application is updated again, the id turns out to be generated in json and after that I already get data about the user.

How to fix it? In fact, it must first receive the id, and only then the id is sent and the data is received, however, at the first entry into the application, he does not want to receive the ID immediately, but only after a reboot (ctlr + s in VS code)

//LOGIN.js

import React, { Component } from 'react';
import { View, Pressable, Text, TextInput, TouchableOpacity } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import styles from './style';


export default class Login extends Component {
  constructor(props) {
    super(props);
    this.state = {
      email : '',
      password : '',
      check_textInputChange : false,
      secureTextEntry : true,
      id : '',
     };
  }

  componentDidMount(){
    this._loadInitialState().done();
  }

//Сheck that the user with id does not throw out on the authorization screen when exiting the application:

  _loadInitialState = async () => {
    var id = await AsyncStorage.getItem('id');
    if (id !== null) {
      this.props.navigation.navigate("HomeScreen")
      this.id = id
    }
  }

  InsertRecord () {
    var Email = this.state.email;
    var Password = this.state.password;

    if ((Email.length==0) || (Password.length==0)){
      alert("Missing a required field!");
    }else{
      var APIURL = "http://10.0.2.2:8080/SignIn/login.php";

      var headers = {
        'Accept' : 'application/json',
        'Content-Type' : 'application/json'
      };
            
      var Data ={
        Email: Email,
        Password: Password
      };

      fetch(APIURL,{
        method: 'POST',
        headers: headers,
        body: JSON.stringify(Data)
      })
      .then((Response)=>Response.json())
      .then((Response)=>{
        alert(Response[0].Message)
        if (Response[0].Message == "Success") {
          console.log(Response[0].Message)
          // eslint-disable-next-line react/prop-types
          AsyncStorage.setItem('id',Response[0].Id);
          this.props.navigation.navigate("HomeScreen");
          console.log(Response[0].Id);
        }
        console.log(Data);
      })
      .catch((error)=>{
        console.error("ERROR FOUND" + error);
      })
    }
  }

  updateSecureTextEntry(){
    this.setState({
      ...this.state,
      secureTextEntry: !this.state.secureTextEntry
    });
  }

  render() {
    return (
      <View style={styles.viewStyle}>
          <View style={styles.action}>
            <TextInput
              placeholder="Enter Email"
              placeholderTextColor="#ff0000"
              style={styles.textInput}
              onChangeText={email=>this.setState({email})}
              />
          </View>

          <View style={styles.action}>
            <TextInput
              placeholder="Enter Pass"
              placeholderTextColor="#ff0000"
              style={styles.textInput}
              secureTextEntry={this.state.secureTextEntry ? true : false}
              onChangeText={password=>this.setState({password})}
              />
                <TouchableOpacity
                  onPress={this.updateSecureTextEntry.bind(this)}>
                </TouchableOpacity>  
          </View>


                {/* Button */}

                <View style={styles.loginButtonSection}>    
                  <Pressable
                    style={styles.loginButton} 
                    onPress={()=>{
                      this.InsertRecord()
                    }}
                    >
                      <Text style={styles.text}>Войти</Text>
                  </Pressable>
                </View>
      </View>
    );
  }
}

//INFOSTATUS.js

import React, { useEffect, useState } from 'react';
import { ActivityIndicator, TouchableOpacity, SafeAreaView, FlatList, StyleSheet, Button, View, Text } from 'react-native';
import { useNavigation } from '@react-navigation/native'
import AsyncStorage from '@react-native-async-storage/async-storage';

function InfoStatus() {
    const [isLoading, setLoading] = useState(true);
    const [data, setData] = useState([]);
    const [idUser, setIdUser] = useState();

//check ID  
    const idcheck = async () => {
        try {
          const get = await AsyncStorage.getItem('id')
          setIdUser (get)
        } catch(e) {
          // read error
        }
      }

//Sending data to api and getting user data

    const getNotifications = async () => {
        const send = {
            id:idUser
        }
     try {
      const response = await fetch('http://10.0.2.2:8080/InfoStatus/InfoStatus.php', {
        method: 'POST', 
        body: JSON.stringify(send), 
        headers: {
          'Content-Type': 'application/json'
        }
      });
      const data = await response.json();
      setData(data);
      console.log(data);
    } catch (error) {
      console.error(error);
    } finally {
      setLoading(false);
    }
  }
  
   useEffect(() => {
    idcheck();
    getNotifications();
  }, []);

  //Initialization of received data

const Item = ({ name, middlename,status,number,city }) => (

   <View style={StyleInfo.container}>
    <View style={StyleInfo.container2}>
    <Text style={StyleInfo.TextStyle}> Dear, </Text>
    <Text style={StyleInfo.TextStyleData} key ={name}> {name} {middlename} </Text> 
    </View>
    <View style={StyleInfo.container2}>
    <Text style={StyleInfo.TextStyle}> Number: </Text>
    <Text style={StyleInfo.TextStyleData}key ={number}> № {number} </Text> 
    <TouchableOpacity 
         onPress={() =>
            navigation.navigate('InfoParser')
            }
          >
           <Text style={StyleInfo.ButtonAdress}>Find out the address</Text>
        </TouchableOpacity>
    </View>
    <View style={StyleInfo.container2}>
    <Text style={StyleInfo.TextStyle}> Status: </Text>
    <Text style={StyleInfo.TextStyleData} key ={status}> {status} </Text> 
    </View>
    <View style={StyleInfo.container2}>
    <Text style={StyleInfo.TextStyle}> City: </Text>
    <Text style={StyleInfo.TextStyleData} key ={city}> {city} </Text> 
    </View>
       <TouchableOpacity 
         style={StyleInfo.Button}
         onPress={() =>
            navigation.navigate('InfoParser')
            }
          >
           <Text style={StyleInfo.TextButton}>Get contacts of friends</Text>
        </TouchableOpacity>
    </View>
    
    );
  
  const renderItem = ({ item }) => (
    <Item name={item.name} middlename={item.middlename} status={item.status} yik={item.yik} elections={item.elections} />
    
  );
  
  return (
  <SafeAreaView>
  {isLoading ? <ActivityIndicator size="large" color="#00ff00"/> : (
      <FlatList
        data={data}
        renderItem={renderItem}
        keyExtractor={item => item.id}
      />
  )}
    </SafeAreaView>
  );
}

const StyleInfo = StyleSheet.create({
    
    container:{
        width: 390,
        height: 190,
        borderWidth: 1,
        borderRadius: 2,
        marginLeft: 10,
        marginBottom: 10,
        backgroundColor: '#E9E9E9',
    },
    container2:{
        flexDirection: "row",
    },
    TextStyle: {
        fontFamily: 'Raleway',
        fontStyle: 'normal',
        fontWeight: 'normal',
        fontSize: 18,
        marginTop: 5,
        marginLeft: 5,
        bottom: 10,
        top: 10
    },
    TextStyleData: {
        fontSize: 18,
        marginTop: 5,
        top: 10,
        fontWeight: 'bold',
    },
    ButtonAdress: {
        fontSize: 18,
        marginTop: 5,
        marginLeft: 20,
        top: 10,
        color: "#ff0000",
    },
    Button: {
    width: 310,
    height: 40,
    marginTop: 10,
    marginLeft: 5,
    bottom: 10,
    borderWidth: 1,
    borderRadius: 2,
    top: 10,
    alignSelf: 'center',
    backgroundColor: "#ff0000",
    },
    TextButton: {
    marginTop: 5,
    fontSize: 16,
    alignSelf: 'center',
    fontWeight: 'bold',
    color: 'white',
    
    }
}
)

export {InfoStatus}

PS: I also caught one thing that when I try to get an id via async / await, then most likely the point is that it does not have time to get the value before rendering. I have run out of ideas, I would like to receive more other suggestions

PSS: I also know that in fact, even if I passed the value through the navigator, I would pass it to the homescreen. Although my InfoStatus is embedded in the Homescreen and I need to somehow pass this parameter there.

Although in general the question interests me a lot, because I will need this parameter everywhere. Therefore, finding one universal solution would be cool.


Solution

  • I am not 100% sure I understand the question so here a few hints I would give you.

    1. You can pass parameters when navigating like this:
    navigation.navigate('somescreen', {
                param: 86,
                otherParam: 'myBestFriendTheParam',
              })
    

    On the next screen you have to then read it from the route.params.

    1. You could use redux to have your user data at hand while the app is open and user logged in? That would give you the data where ever you want basically.

    2. If async/wait does not work why don't you use then-chains like in the rest of your code?