skip to Main Content

I am trying to modularise my code so im trying to separate the data that is being read

here is my previous code that works without error:

function Home({navigation, route}): React.JSX.Element {
   const [showAddBillModal, setShowAddBillModal] = useState(false)
   const isDarkMode = useColorScheme() === 'dark';
   const backgroundStyle = {
      backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
    };

    const toggleShowAddBillModal = () => {
       setShowAddBillModal(!showAddBillModal)
  }

   // const user = getLoggedInUser() //works

    return (...)

but when i try to modularise it by separating the user data read into another file/class:

login page:

const login = (text, navigation) =>{
let userData = getLoggedInUser(text)
if(userData !== null || userData !== undefined){
    () => navigation.navigate('Home', {user: userData})
}
}

function Login({ navigation }): React.JSX.Element {
const [name, onChangeNameText] = React.useState('');
const isDarkMode = useColorScheme() === 'dark';
const backgroundStyle = {
    backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
};

// const user = getLoggedInUser()
return (....
                <Pressable
                    style={[styles.button, styles.buttonClose]}
                    onPress={() => login(name, navigation)}
                    >...
)
}

file to read data:

export default getLoggedInUser = async (name) => {
const [userData, setUserData] = useState(null)
// const userData = null
try{
    console.log("test")
    await firestore()
        .collection('users')
        .get()
        .then(querySnapshot => {
            querySnapshot.forEach(doc => {
                if (doc.data().name == name) {
                    setUserData(doc)
                    // return doc
                    // userData = doc
                    // return userData
                }
            });
        });
        return userData
}
catch(error){
    console.log(error)
}
}

i get invalid hook call here
i have tried normally doing "function name() {hook ….}" but it also gives the same error, its working everywhere except this part

2

Answers


  1. Chosen as BEST ANSWER

    solved it, my stubborn mind did not think of placing the usestate hook at the front for 3 whole days :D

    login page:

    function Login({ navigation }): React.JSX.Element {
        const [userData, setUserData] = useState(null)
        const login = async () => {
            try {
                console.log("presslogin")
            //   const user = await getLoggedInUser(name, setUserData);
            await getLoggedInUser(name, setUserData)
            // console.log(user)
            //   if (user) {
                navigation.navigate('Home', { userData });
            //   }
            } catch(error) {
              // handle/ignore/etc
            }
    }
    

    backend:

    export default getLoggedInUser = async (name, setUserData) => {
    try {
        const users = await firestore()
            .collection('users')
            .get()
            .then(querySnapshot => {
                querySnapshot.forEach(doc =>{
                    if (doc.data().name == name) {
                        setUserData(doc);
                    }
                })
        });
        // return userData;
    } catch (error) {
        console.log(error);
        // re-throw for callers
        throw error;
    }
    }
    

    i will be accepting my own answer but for anyone who wants to see a solution with custom hook see Drew Reese's answer :)


  2. You cannot call React hooks outside React components or custom React hooks as this breaks the Rules of React Hooks.

    You could convert your getLoggedInUser function into a React hook so that I can also use the useState hook. I’d suggest returning a function the UI can call to initiate the data fetching from your firestore backend.

    Example Implementation:

    export default useGetLoggedInUser = () => {
      const [userData, setUserData] = useState(null);
    
      const getLoggedInUser = async (name) => {
        try {
          const users = await firestore()
            .collection('users')
            .get();
    
          let userData = null;
          querySnapshot.forEach(doc => {
            if (doc.data().name == name) {
              setUserData(doc);
            }
          });
            
          return userData;
        } catch(error) {
          console.log(error);
          // re-throw for callers
          throw error;
        }
      };
      
      return {
        userData,
        getLoggedInUser,
      };
    }
    

    Move the login handler into the Login component to close over name and navigator in callback scope. Call your new useGetLoggedInUser hook and access the returned getLoggedInUser function, to be called in the login callback. await its return value, and if truthy, issue the navigation action.

    function Login({ navigation }): React.JSX.Element {
      const [name, onChangeNameText] = React.useState('');
      const isDarkMode = useColorScheme() === 'dark';
    
      const { getLoggedInUser } = useGetLoggedInUser();
    
      const backgroundStyle = {
        backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
      };
    
      const login = async () => {
        try {
          const user = await getLoggedInUser(name);
    
          if (user) {
            navigation.navigate('Home', { user });
          }
        } catch(error) {
          // handle/ignore/etc
        }
      };
    
      return (
        ...
        <Pressable
          style={[styles.button, styles.buttonClose]}
          onPress={login}
        >
          ...
        </Pressable>
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search