Mares
Mares

Reputation: 51

Reload 2 times useEffect - React Native and SQLite (expo)

I'm new to react native, so I apologize for errors in the code. First: I use Android Studio, VS Code, react native(expo) and sqlite(expo), supporting only android (I haven't programmed for ios yet).

I have a serious problem in my code and I have no idea how to start. The 'useEffect', to work, you have to save the file 2 times (ctrl+s in vs code). Don't just open the app.

THIS IS MY LOGIN PAGE login.js

import React, {useState,useEffect} from 'react';
import {View,Text,Pressable,Image,FlatList,ImageBackground,Alert} from 'react-native';
import {TextInput} from 'react-native-gesture-handler';
import fundoLogin from './styleLogin';
import Tb_user from '../../src/models/tb_user';
import Tb_veic_user from '../../src/models/tb_veic_user';
import db from "../../src/services/SQLiteDatabse";
import NetInfo from '@react-native-community/netinfo';

const printUser = (user) => {
    console.log(`ID_user:${user.ID_user}, username:${user.username}, senha:${user.senha}, ID_empresa:${user.ID_empresa}, nome_empresa:${user.nome_empresa}, status_user:${user.status_user}`)
}
const printV = (v) => {
    console.log(`ID_veic_uso:${v.ID_veic_uso}, username:${v.username}, placa:${v.placa}, atividade:${v.atividade}, data_inic:${v.data_inic}, km_inic:${v.km_inic}, data_final:${v.data_final}, km_final:${v.km_final}, obs:${v.obs}, integrado:${v.integrado}`)
}
function Login({ navigation, route }) {
  const [username, setUsername] = useState("")
  const [password, setPassword] = useState("")
  const [errorLogin, setErrorLogin] = useState("")
  const [users, setUsers] = useState([])
  const [net, setNet] = useState("")
  const [dadosVeic, setDadosVeic] = useState([])
  const [info, setInfo] = useState([])



    const findTbVeic = (id) => {
        return new Promise((resolve, reject) => {
            db.transaction((tx) => {
                tx.executeSql(
                "SELECT * FROM tb_veic_user WHERE integrado=0 AND km_final IS NOT NULL ;",
                [],
                //-----------------------
                (_, { rows }) => {
                    if (rows.length > 0) {
                        resolve(rows._array)
                    }
                    else {
                        reject("Obj not found: id=" + id);
                    } // nenhum registro encontrado
                },
                (_, error) => reject(error) // erro interno em tx.executeSql
                );
            });
        });
    };

    useEffect(() => {
          NetInfo.fetch().then(state => {
            setNet(state.isConnected)
          });
          
        if (net === true) {

        findTbVeic()
        .then(a => setDadosVeic(a))
            .then( dadosVeic.map(item => {
                // ENVIA DADOS PARA A API
                fetch('url API', {
                    method: 'POST',
                    body: JSON.stringify({
                        username: item.username,
                        placa: item.placa,
                        atividade: item.atividade,
                        data_inic: item.data_inic,
                        km_inic: item.km_inic,
                        data_final: item.data_final,
                        km_final: item.km_final
                    }),
                    headers: {
                        'Content-type': 'application/json; charset=UTF-8',
                    },
                })
                //ALTERA O 'INTEGRADO' == 1
                Tb_veic_user.updateV( item.ID_veic_uso )
            }))
        }else{
            console.log('sem conexao com a internet')
        }
    },[])

  const importTbUser = () => {
    // DADOS DA API SALVA EM CONST USERS
    fetch('url API')
    .then( res => res.json())
    .then( 
        (dado) => {
            setUsers(dado.data)
        }            
    )

    // INSERE, NO BANCO DE DADOS, OS DADOS DA API
    const a = users.map((element) => {
        Tb_user.create({ID_user:element.ID_user, username:element.username, senha:element.senha, ID_empresa:element.ID_empresa, nome_empresa:element.nome_empresa, status_user:element.status_user})
    });
  }

  const login = () => {
    // FAZER LOGIN
        return new Promise((resolve, reject) => {
            db.transaction(tx => {
                tx.executeSql(
                'SELECT ID_user, username, senha FROM tb_user WHERE username = ? and senha = ? LIMIT 1;',
                    [username, password],
                    //-----------------------
                    (_, { rows }) => {
                        if (rows.length > 0){ 
                            resolve(rows._array), 
                            navigation.navigate('Veic', { 
                                paramKey: username,
                            })
                        }else{ 
                            reject("Obj not found");
                        } // nenhum registro encontrado
                      },
                      (_, error) => reject(error)  // Success
                );
            });
        });
  }

  return (
    <View style={fundoLogin.container}>
        <ImageBackground
        source={require('../../imagens/1.jpg')} 
        style={fundoLogin.imageFundo} 
        >    
          <Image
              style={fundoLogin.imageLogo}
              source={require('../../imagens/logo_cymi.png')}
          />   

            {net === true ?
            <Image
                style={{height:30,width:30}}
                source={require('../../imagens/signal.png')}
            />
        :  
            <Image
                style={{height:30,width:30}}
                source={require('../../imagens/no-signal.png')}
            />
        }

          <TextInput
              style={fundoLogin.input}
              placeholder='Digite seu email'
              onChangeText={txtUsername => setUsername(txtUsername)}
              value={username}
          />

          <TextInput
              style={fundoLogin.input}
              placeholder='Digite sua senha'
              secureTextEntry={true}
              onChangeText={txtPassword => setPassword(txtPassword)}
              value={password}
          />

          {errorLogin === true
          ?
              <View>
                  <Text style={fundoLogin.error}>email ou senha inválido</Text>
              </View>
          :
              <View>
              </View>
          }

          {(username === "" || password === "")
          ?
              <Pressable 
              disabled={true}
              style={fundoLogin.button} 
              >
                  <Text style={fundoLogin.textButton}>Login</Text>
              </Pressable>
          :
            <Pressable 
            style={fundoLogin.button} 
            onPress={login}
            >
                <Text style={fundoLogin.textButton}>Login</Text>
            </Pressable>
          }

        <Pressable 
          style={fundoLogin.button}
          onPress={importTbUser}
          >
              <Text style={fundoLogin.textButton}>Importar</Text>
        </Pressable>

          <Pressable
          style={fundoLogin.info} 
          onPress={navigation.navigate('Info')}
          >
              <Text style={fundoLogin.textInfo}>?</Text>
          </Pressable>
      </ImageBackground>
    </View>
  );
}
export default Login;

My app works like this: it starts on the login page (where there is a login button, import button and a company information button) and goes to another page to select a vehicle (this 'veic' page also has the same problem in useEffect). All components are working perfectly fine, I've checked all possible console.logs, and it's running fine. The only problem is that use effect doesn't work (on this page it has to be run 2x to refresh, on the 'veic' page it only does one thing, and the others don't). If anyone can tell me more, please. I don't even know if it's an error in my code or in Android Studio. Thank you in advance!!!

Upvotes: 0

Views: 732

Answers (2)

Maximilian Dietel
Maximilian Dietel

Reputation: 1128

The problem is that you are not awaiting NetInfo.fetch(). Write the code under NetInfo.fetch() in NetInfo.fetch().then(... your remaining useEffect code...). Like this:

useEffect(() => {
  NetInfo.fetch().then((state) => {
    if (state.isConnected) {
        findTbVeic()
        .then(a => setDadosVeic(a))
            .then( dadosVeic.map(item => {
                // ENVIA DADOS PARA A API
                fetch('url API', {
                    method: 'POST',
                    body: JSON.stringify({
                        username: item.username,
                        placa: item.placa,
                        atividade: item.atividade,
                        data_inic: item.data_inic,
                        km_inic: item.km_inic,
                        data_final: item.data_final,
                        km_final: item.km_final
                    }),
                    headers: {
                        'Content-type': 'application/json; charset=UTF-8',
                    },
                })
                //ALTERA O 'INTEGRADO' == 1
                Tb_veic_user.updateV( item.ID_veic_uso )
            }))
        }else{
            console.log('sem conexao com a internet')
    }
  });
}, []);

For your other useEffect: The problem is that you can't change a state and than use that state in an useEffect drectly after. This is cause of the execution of the useEffect. It will only rerender when variables in the useEffect array change. For example:

const Test = () => {
  const [test, setTest] = useState(false);

  useEffect(() => {
    fetchTest().then((data) => {
      // lets say data.test is "true"
      setTest(data.test); // set to true

      // states in useEffect will keep the value they had when the useEffect started

      // DONT:
      console.log("test:", test): // --> "test: false"

      // DO
      console.log("test:", data.test): // --> "test: true"
    });
  }, []);
}

Upvotes: 1

Mares
Mares

Reputation: 51

I understood what Maximilan said, and on that login page it worked really well. But on the 'veic' page I'm not so lucky

useEffect(() => {
        findByUserna( route.params.paramKey )
        .then(
            findByV(route.params.paramKey)
            .then( 
                d => setDados(d)            
            ),
            console.log('use effect 1 ------>',dados)
        )
        .then( 
            dados.map(
                item => setIDVeic(item.ID_veic_uso)
            ),
            console.log('use effect 2 ------>',IDVeic)
        )
},[])

When opening the screen, the consoles are empty, the variable is not saved, but when updating, it works, the variables are saved and shown in the console normally:

//The first time, console:

use effect 1 ------> Array []
use effect 2 ------> null
ENCONTRADO de tb_user o ID_user, username, nome_empresa --->  SORAIA
ENCONTRADO de tb_veic_user o ID_veic_uso onde kmf=null

//The second time, console:

use effect 1 ------> Array [
  Object {
    "ID_veic_uso": 4,
  },
  Object {
    "ID_veic_uso": 7,
  },
]
use effect 2 ------> 7

Upvotes: 0

Related Questions