Home > Software engineering >  React js How to get Value within a useEffect and display on defualtValue textfield
React js How to get Value within a useEffect and display on defualtValue textfield

Time:11-27

I'm trying to get the value of userData which is from a promise in firebase and set that value on my TextField defaulValue when the page loads. But the page loads first before the value can be placed which makes it default:undefined. How can I make my page load with the defaultValue?consoleLog

import React from 'react'
import { useEffect, useState } from 'react';
import { Grid, TextField} from '@mui/material';
import { useAuth } from '../../contexts/AuthContext';
import { db } from '../../firebase'
import { getDoc, doc } from '@firebase/firestore';


export default function useEditUser() {

    const { currentUser } = useAuth();
    const [newDisplayName,setDisplayName] = useState("");
    const documentId = currentUser.uid
    const [userData, setUserData] = useState([]);

    useEffect(() =>{
        const getUsers = async()=>{
            const docRef =  doc(db, "user", documentId)
            await getDoc(docRef).then(res => {
                console.log(res.data().user_fields)
                setUserData(res.data().user_fields)
            }).catch(err => {
                console.log(err)
            })
        }
        getUsers()
    },[]);
    

    return (
        
        <form>
            <Grid container columnSpacing={1} rowSpacing={1} direction="row" justifyContent="center" alignItems="center" marginBottom={1}>
                <Grid item xs={11} sm={8} md={3}>
                    <TextField defaultValue={console.log("default:"   userData.displayname)} error={newDisplayName===""} defaultValue={userData.displayname} helperText={newDisplayName === "" ? 'Required' : ' '} label="User Display Name*" id="outlined-required" type="text" variant="outlined"  onChange={(event) => {setDisplayName(event.target.value)}} sx={{width: '100%'}} />
                </Grid>
            </Grid>     
        </form>
            
    )
}

CodePudding user response:

You can use a loading state with default value true to render the textField when loading is false and when you get the data from the api then you will set the loading to false. Which will render that field with default value that you want Refer to the following code

export default function useEditUser() {
    const { currentUser } = useAuth();
    const [newDisplayName,setDisplayName] = useState("");
    const documentId = currentUser.uid
    const [userData, setUserData] = useState([]);
    const [loading,setLoading]=useState(true)

    useEffect(() =>{
        const getUsers = async()=>{
            setLoading(true);
            const docRef =  doc(db, "user", documentId)
            await getDoc(docRef).then(res => {
                console.log(res.data().user_fields)
                setUserData(res.data().user_fields)
                setLoading(false)
            }).catch(err => {
                console.log(err)
                setLoading(false)
            })
        }
        getUsers()
    },[]);
    

    return (
        
        <form>
            <Grid container columnSpacing={1} rowSpacing={1} direction="row" justifyContent="center" alignItems="center" marginBottom={1}>
                <Grid item xs={11} sm={8} md={3}>
                   {!loading? <TextField defaultValue={console.log("default:"   userData.displayname)} error={newDisplayName===""} defaultValue={userData.displayname} helperText={newDisplayName === "" ? 'Required' : ' '} label="User Display Name*" id="outlined-required" type="text" variant="outlined"  onChange={(event) => {setDisplayName(event.target.value)}} sx={{width: '100%'}} /> :""}
                </Grid>
            </Grid>     
        </form>   
    )
}

CodePudding user response:

Try to use optional chaining.

At bottom in render just add the question mark: userData?.displayname

CodePudding user response:

defaultValue is used to insert data when you don't have the data yet. In your case, it doesn't even need to be populated, value needs to be. In the defaultValue and value props, you need to specify strings, but in your code you are putting functions. Also, you cannot use objects, unless you stringify them with JSON.stringify(userData). You also need to specify the prop only once.

So you can use something like this:

    return (
        
        <form>
            <Grid container columnSpacing={1} rowSpacing={1} direction="row" justifyContent="center" alignItems="center" marginBottom={1}>
                <Grid item xs={11} sm={8} md={3}>
                    <TextField value={userData?.displayname} sx={{width: '100%'}} />
                </Grid>
            </Grid>     
        </form>
            
    )

  • Related