En un componente, asigné cada elemento de una matriz que proviene de una API y los devuelvo en un <li> cada uno, así:
const usersComponent = usersData.map((user: any) => ( <li key={user.Username} className="px-4 my-2 lg:pl-8 w-full scale-95 transform transition duration-500 hover:scale-100" > \\ rest of the codeLuego, en el componente, hago:
return ( <ul>{usersComponent}</ul> ) Ahora, cada elemento de esta lista es un nombre de username en mi API, y estos nombres de usuario tienen grupos en mi base de datos, pero los grupos solo regresan en otro GET de la API, que tengo en esta otra función:
async function listGroupsForUser(username: string) { const apiName = 'AdminQueries' const path = '/listGroupsForUser' const myInit = { body: { username }, headers: { 'Content-Type': 'application/json', Authorization: `${(await Auth.currentSession()) .getAccessToken() .getJwtToken()}`, }, } return await API.get(apiName, path, myInit) } Entonces, necesito pasar este listGroupsForUser para cada uno de los <li> que mapeé, luego devolverá una matriz para cada uno de ellos, y necesito mapearlo, para cada uno, individualmente.
Lo intenté de muchas maneras pero no pude hacerlo.
Depende de si necesita obtener todos los datos por adelantado o si puede obtener los grupos de forma asíncrona.
Para buscarlos todos por adelantado, puede usar Promise.All y disparar las consultas en paralelo como:
const getRandomDelay = (min: number, max: number): number => { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1) + min); }; // mock API call const fetchGroups = (username: string): Promise<string[]> => { return new Promise((resolve) => { setTimeout(() => { return resolve(['admin', 'editor']); }, getRandomIntInclusive(2000, 4000)); }); }; const data = ['darth', 'fett', 'luke']; interface User { name: string; groups?: string[]; } export default function App() { const [users, setUsers] = useState<User[] | null>(null); useEffect(() => { Promise.all( data.map(async (user) => { const groups = await fetchGroups(user); return { name: user, groups: groups }; }) ).then((result) => { setUsers(result); }); }, []); return ( <div className="App"> {users && users.map((user) => ( <div key={user.name}> {user.name} {user.groups.map((group) => ( <span key={group}>{group}, </span> ))} </div> ))} </div> ); }Alternativamente, podría usar un gancho dentro de cada uno. Algo como:
const useListGroupsForUser = (username: string) => { const [groups, setGroups] = useState<string[] | null>(null); useEffect(() => { console.info(`mocking fetch for ${username}`); fetchGroups(username).then((result) => setGroups(result)); }, [username]); return { groups }; }; // User component const User = ({ user }: UserProps) => { const { groups } = useListGroupsForUser(user); return ( <li> {user} <br /> {groups ? groups.map((group) => group) : <span>loading groups...</span>} </li> ); }; // and render in App {data.map((user) => ( <User key={user} user={user}/> ))}