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
?
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>
)