I can't understand correctly how to update my useState. I'm receiving data via my Axios call so "applis" is not empty but it's the following that seems to stuck.
What I'm trying to do:
I can display in my Accordions my different applications but in AccordionSummary, you can see that I can't get my API list for an application.
Either I have nothing (as in this post) or all the APIs are under an application to loop over and over again...
Here is my code:
export default function documentationv2() { // Getteur - Setteur const [applis, setApplis] = useState([]); const [applicationSelect, setApplicationSelect] = useState([]); const [APIs, setAPIs] = useState([]); // Chargement const loadRessources = () => { axios.get('/api/documentation/application').then((response) => { setApplis(response.data); console.log('LesApplications: ' + JSON.stringify(response.data)) {applis.map((application) => ( setApplicationSelect(application.IDAPPLI) ))} ListeAPI(applicationSelect); }).catch((error) => console.log(error)); } const ListeAPI = (AppliID) => { console.log('SELECT: ' + AppliID) // console.log('ID: ' + AppliID) axios.get('/api/documentation/api?app_id=' + AppliID).then((response) => { setAPIs(response.data) console.log('LesAPIS: ' + response.data) }) {APIs.map((api, index) => ( console.log('API: ' + api.api_uri) ))} } useEffect(() => { console.log('Chargement....') loadRessources(); }, []) // useEffect(() => { // console.log('-> Application SELECT: ' + applicationSelect) // axios.get('/api/documentation/api?app_id=' + 1) //.then((response) => { // setAPIs(response.data) // console.log('-> APIs: ' + response.data) // }) // }, [applicationSelect]) return ( {/* -- BODY -- */} <Grid item className={classes.Body}> <Grid container className={classes.GridContainerBody}> {applis.map((application, index) => ( <div className={classes.DivContainerBody}> <Grid item className={classes.GridItemLeftBody}> <Accordion key={application.IDAPPLI} onChange={(event) => setApplicationSelect(application.NOMAPPLI)} className={classes.AccordionBody}> <AccordionSummary expandIcon={<IconButton className={classes.ButtonBodyShow} disableRipple={true}><ExpandMoreIcon/></IconButton>}> <Typography> {application.NOMAPPLI} - ({application.NBAPI}) </Typography> </AccordionSummary> <AccordionDetails className={classes.AccordionDetailsApplication}> {/* {ListeAPI(application.IDAPPLI)} */} {/* {APIs.map((api, index) => ( <div className={classes.DivDetailsApplication}> <Accordion key={index} className={classes.AccordionBody}> <AccordionSummary expandIcon={<IconButton className={classes.ButtonBodyShow} disableRipple={true}><ExpandMoreIcon/></IconButton>}> <div className={classes.AccordionSumAPI}> <Typography> {api.api_uri} </Typography> <Typography> {api.api_description} </Typography> <div className={classes.AccordionSumAPIDiv}> <Chip style={{backgroundColor: "#06d6a0"}} label={api.api_version} /> <Chip style={{backgroundColor: "#ffd166"}} label={api.api_response_type} /> </div> <div> <Typography> Créé par {api.api_creation_user} le {api.api_date_creation}. </Typography> <Typography> Modifié par {api.api_maj_user} le {api.api_date_maj}. </Typography> </div> </div> </AccordionSummary> <AccordionDetails> <Typography> Information </Typography> </AccordionDetails> </Accordion> </div> ))} */} </AccordionDetails> </Accordion> </Grid> <Grid item className={classes.GridItemRightbody}> <div> <Tooltip title="Mot de passe" placement="top" arrow> <IconButton className={classes.ButtonHeader} disableRipple={true} > <LockIcon/> </IconButton> </Tooltip> </div> <div> <Tooltip title="Télécharger doc " placement="top" arrow> <IconButton className={classes.ButtonHeader} disableRipple={true} > <GetAppIcon/> </IconButton> </Tooltip> </div> </Grid> </div> ))} </Grid> </Grid> </Grid> ) }
What the different console.log tells me:
LesApplications : [{"NOMAPPLI" : "NameValue", "IDAPPLI" : "IdValue", "NBAPI" : "ValueCount"}, ...]
SELECT :
LesAPIS :
Could someone explain my mistake? It must be something with the useEffect not re-rendering? I don't really understand everything here.
Sorry in advance if the title of my question does not seem clear
setApplis
is asyncronous, you can't call applis.map
after setApplis
because your applis
isn't updated yet. You must call applis.map
in useEffect
with dependency on it. Then in second useEffect
you call ListeAPI(applicationSelect)
with actual applicationSelect
array.
Example:
const loadRessources = () => {
axios.get('/api/documentation/application')
.then((response) => {
setApplis(response.data);
console.log('LesApplications : ' + JSON.stringify(response.data))
})
.catch((error) => console.log(error));
}
useEffect(() => {
const arr = applis.map((application) => application.IDAPPLI);
setApplicationSelect(arr);
}, [applis]);
useEffect(() => {
applicationSelect.length && ListeAPI(applicationSelect);
}, [applicationSelect]);
useEffect(() => {
loadRessources();
}, [])
Another example:
const ListeAPI = (AppliID) => {
axios.get('/api/documentation/api?app_id=' + AppliID)
.then((response) => {
setAPIs(prev => [...prev, ...response.data])
console.log('LesAPIS : ' + response.data)
})
}
const loadRessources = () => {
axios.get('/api/documentation/application')
.then((response) => {
setApplis(response.data);
console.log('LesApplications : ' + JSON.stringify(response.data))
})
.catch((error) => console.log(error));
}
useEffect(() => {
applis.length && applis.forEach((application) => ListeAPI(application.IDAPPLI));
}, [applis]);
useEffect(() => {
loadRessources();
}, [])
Example how to do correct APIs
object sctructure:
const [APIs, setAPIs] = useState({});
const ListeAPI = (AppliID) => {
axios.get('/api/documentation/api?app_id=' + AppliID)
.then((response) => {
setAPIs(prev => {
return {
...prev,
[AppliID]: response.data
}
})
})
}
JSX, then you can find needed api by applis id:
{applis.map((application, index) => (
...
{APIs[application.IDAPPLI] && APIs[application.IDAPPLI].map((api, index) => (
...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.