I have some objects that I got from map() an API URL then fetch() those URLs and got these objects as the return (see the picture).
So I want to put all of these objects into a new array so I can use the array to create a react component that will use the information from there.
Could anyone help me out to figure it out to give me some hint on how to solve this problem? thanks before.
const url = "https://pokeapi.co/api/v2/pokemon?offset=0&limit=5";
const AppProvider = ({ children }) => {
const fetchUrl = async () => {
const resp = await fetch(url);
const respData = await resp.json();
const data = respData.results;
data.map((pokemon) => {
fetchPokemon(pokemon);
});
};
const fetchPokemon = (pokemon) => {
let url = pokemon.url;
fetch(url)
.then((resp) => resp.json())
.then((pokemonData) => {
finalData(pokemonData);
});
};
const finalData = (pokemonData) => {
console.log(pokemonData, "data");
};
};
You can create your desired array of object by returning your data in map function and then push it into array.
const url = "https://pokeapi.co/api/v2/pokemon?offset=0&limit=5";
const AppProvider = ({ children }) => {
const fetchUrl = async () => {
const resp = await fetch(url);
const respData = await resp.json();
const data = respData.results;
const newArray = [];
data.map((pokemon) => {
newArray.push(fetchPokemon(pokemon));
});
};
const fetchPokemon = async (pokemon) => {
let url = pokemon.url;
let data = {}
return fetch(url)
.then((resp) => resp.json())
.then((pokemonData) => {
return pokemonData;
});
};
};
Related
I have three apis in all. GetAssets is the first, followed by assetsOptionsList and getAssetsLibrary. The issue I'm having is that when I post the data on getAssetsLibrary, I want to be able to present it on get Assets at runtime.Everything is working fine but i want to show assets on runtime.
I'm setting the runTime state true on get request but the problem is it works only for one time.Second time, it does not map on runtime. Actually, i want to know is there any alternative so that i can achieve the goal.
In the below code the one function is getting the assets. And i want to run the one function when the post request successfully sent.
const [images, setImages] = useState([]);
const [assetOptions, setAssetOptions] = useState([]);
const [faqOpened, setToggleFaq] = useState(false);
const [runTime, setRunTime] = useState(false)
const [assetID, setAssetID] = useState()
const [isLoading, setIsLoading] = useState(false);
const handleForm = (e) => {
const index = e.target.selectedIndex;
const el = e.target.childNodes[index]
const option = el.getAttribute('id');
setAssetID(option)
}
const formHandler = (e) => {
e.preventDefault()
let formData = new FormData();
formData.append('media', e.target.media.files[0]);
formData.append('assetListId', assetID)
formData.append('name', e.target.name.value);
console.log(Object.fromEntries(formData))
const res = axios.post('api/asset-library',
formData
).then((response) => {
showSuccessToaster(response?.data?.message)
setRunTime(true)
setToggleFaq(false)
})
.catch((error) => {
showErrorToaster(error?.response?.data?.message)
})
}
const showSuccessToaster = (response) => {
return uploadToasterSuccess.show({ message: response });
}
const showErrorToaster = (error) => {
return uploadToasterError.show({ message: error });
}
const one = async () => {
setIsLoading(true)
const data = await axios.get('api/assets').then((res) => {
return res?.data?.data
})
setImages(data)
setIsLoading(false)
}
const two = async () => {
const data = await axios.get('/api/asset-list').then((res) => {
return res?.data?.data
})
setAssetOptions(data)
}
useEffect(() => {
one()
two()
}, [runTime]);
I'm storing data using API, it saves successfully, but it's not reloading in the datagrid. I have manually refresh the entire page to view the data. I tried to put the storing variable in a function, then call that function, but it's not rendering I guess. kindly help me. Thank you in advance
here's the code
const ContactDataGrid = ({ rows, columns }) => {
const [platform, setPlatform] = useState([]);
const [searchText, setSearchText] = useState('');
const [Rows, setRows] = useState([]);
const [open, setOpen] = useState(false);
const [formInputData, setformInputData] = useState(
{
name: '',
details: '',
}
);
const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
const handleChange = (evnt) => {
setOpen(true)
const newInput = (data) => ({
...data,
[evnt.target.name]: evnt.target.value
});
setformInputData(newInput);
}
const showData = () => setRows(rows);
useEffect(() => {
setPlatform(rows);
showData();
}, [rows]);
console.log()
const handleSubmit = (evnt) => {
evnt.preventDefault();
const formData = new FormData(); //formdata object
formData.append('nickname', formInputData.nickname); //append the values with key, value pair
formData.append('target', formInputData.target);
const config = {
headers: { 'content-type': 'multipart/form-data' }
}
axios.post('http://localhost:8006/api/v2/save/beneficiary', formData, config)
.then(response => {
if (response.data.success === true) {
showData()
alert(response.data.message)
}
})
.catch(error => {
alert(error.message);
});
setformInputData({ nickname: "", target: "" });
setOpen(false);
}
function escapeRegExp(value) {
return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
}
const requestSearch = (searchValue) => {
const searchRegex = new RegExp(escapeRegExp(searchValue), 'i');
const filteredRows = platform.filter((row) => {
return Object.keys(row).some((field) => {
return searchRegex.test(row[field]?.toString() || '');
});
});
setRows(filteredRows);
};
I think when you request success the variable rows don't change so show data load the old data. You can trigger when post data you request fetch data again and change datagrid.
Im working on a star wars api app. I am getting an array of people objects, 10 characters. Who all are their own object with different values. However homeworld, and species are urls. So I have to fetch them and store that data to the correct place. I figured out a way to get the homeworld values to each character. However when I try to do it with species I receive undefined. Would appreciate any help this has been kind of a pain thanks ahead of time !
const [people, setPeople] = useState([]);
const [homeWorld, setHomeWorld] = useState([]);
const [species, setSpecies] = useState([]);
const [nextPageUrl, setNextPageUrl] = useState("https://swapi.dev/api/people/");
const [backPageUrl, setBackPageUrl] = useState('');
const [test, setTest] = useState([]);
const fetchPeople = async () => {
const { data } = await axios.get(nextPageUrl);
setNextPageUrl(data.next);
setBackPageUrl(data.previous);
return data.results;
}
const backPage = async () => {
const { data } = await axios.get(backPageUrl);
setCharacters(data.results);
setNextPageUrl(data.next);
setBackPageUrl(data.previous);
}
// Get People
async function getPeople() {
const persons = await fetchPeople();
const homeWorldUrl= await Promise.all(
persons.map((thing) => axios.get(thing.homeworld)),
);
const newPersons = persons.map((person) => {
return {
...person,
homeworld: homeWorldUrl.find((url) => url.config.url === person.homeworld)
};
});
const newPersons2 = newPersons.map((person) => {
return {
...person,
homeWorld: person.homeworld.data.name
};
});
setPeople(newPersons2);
}
// Get Species
async function getSpecies() {
const persons = await fetchPeople();
const speciesUrl = await Promise.all(
persons.map((thing) => axios.get(thing.species)),
);
const newSwapi = persons.map((person) => {
return {
...person,
species: speciesUrl.find((info) => info.data.url === person.species)
};
});
setTest(newSwapi);
// const newPersons2 = newPersons.map((person) => {
// return {
// ...person,
// homeWorld: person.homeworld.data.name
// };
// });
}
useEffect(() => {
getPeople();
getSpecies();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []); ```
Species property of person is a array, so your getSpecies() should be like
async function getSpecies() {
const persons = await fetchPeople();
const speciesUrl = await Promise.all(
persons
.filter((thing) => thing.species.length)
.map((thing) => axios.get(thing.species[0]))
);
const newSwapi = persons.map((person) => {
return {
...person,
species: speciesUrl.find((info) => info.data.url === person.species[0])
};
});
setTest(newSwapi);
}
I am building a Project with the Pokemon API. Here it is how I am fetching the data:
pokeAPI.js
export const api = {
getPokemonList: async ({ url }) => {
return new Promise((resolve) => {
fetch(url)
.then(res => res.json())
.then(data => {
resolve(data)
})
});
},
getPokemonInfo: async (url) => {
return new Promise((resolve) => {
fetch(url)
.then(res => res.json())
.then(data => {
resolve(data)
})
});
}
};
App.js
const [pokemon, setPokemon] = useState([]);
const URL = 'https://pokeapi.co/api/v2/pokemon?limit=150';
useEffect(() => {
const getPokemonInfo = async () => {
const json = await api.getPokemonInfo(URL);
await loadPokemon(json.results);
};
getPokemonInfo();
}, []);
const loadPokemon = async (data) => {
let pokemonData = await Promise.all(data.map(async pokemon => {
let pokemonList = await api.getPokemonList(pokemon)
return pokemonList
}))
setPokemon(pokemonData);
};
Although this works, it's currently calling getPokemonList for every pokemon and the fact that there are multiple async / await is not helping with readiability. How could I refactor this logic:
const loadPokemon = async (data) => {
let pokemonData = await Promise.all(data.map(async pokemon => {
let pokemonList = await api.getPokemonList(pokemon)
return pokemonList
}))
setPokemon(pokemonData);
};
to fetch only once, using a memoized value in a hook to prevent multiple re-renders?
Thanks for helping.
`there are several ways to do it, you can use redux like state managements or browsers local storage
const App = () => {
const [pokemons, setPokemons] = useState([]);
useEffect(() => {
let pokemons= localStorage.getItem("users");
if (pokemons) {
pokemons = JSON.parse(pokemons);
setPokemons({ pokemons });
} else {
fetch("https://pokeapi.co/api/v2/pokemon?limit=150")
.then(res => res.json())
.then(pokemons => {
setPokemons({ pokemons });
localStorage.setItem("pokemons", JSON.stringify(pokemons));
});
}
}, [])
}
I have to functions getDataOne and getDataTwo. How do I combine below into one function, using fetch(), useState and useEffect?
const MyComponent = () => {
const [loading, setLoading] = useState(false);
const [dataOne, setDataOne] = useState<Data[]>([]);
const [dataTwo, setDataTwo] = useState<Data[]>([]);
const getDataOne = async () => {
setLoading(true);
const result = await fetch(
"https://my-api-link-one"
);
const jsonResult = await result.json();
setLoading(false);
setDataOne(jsonResult);
};
const getDataTwo = async () => {
setLoading(true);
const result = await fetch(
"https://my-api-link-two"
);
const jsonResult = await result.json();
setLoading(false);
setDataTwo(jsonResult);
};
useEffect(() => {
getDataOne();
getDataTwo();
}, []);
Update:
I set it up using Promise.all
const [loading, setLoading] = useState(false);
const [dataOne, setDataOne] = useState<DataOne[]>([]);
const [dataTwo, setDataTwo] = useState<DataTwo[]>([]);
const [data, setData] = useState<DataOne[] & DataTwo>([]);
const urls = [
"https://url-one", "https://url-two",
];
const getData = async () => {
setLoading(true);
const results = await Promise.all(
urls.map((url) => fetch(url).then((res) => res.json()))
);
setLoading(false);
setData(results);
console.log(data);
};
This is not totally working yet. How do I use useState now correctly (and handle both data from urls)? In the end I want to have one data variable so I can map over this variable:
{data.map((item) => {
return (
// etc
So, Promise.all() accepts an array of promises, so naturally Promise.all() returns an array only. So even though your results variable still is an array I would recommend destructuring it because in this case there are only two API fetches involved. Looking at your update, I think there's only small modifications left which are as follows :
const urls = ["https://url-one", "https://url-two",];
const getData = async () => {
setLoading(true);
const [result1, result2] = await Promise.all(
urls.map((url) => fetch(url).then((res) => res.json()))
);
setLoading(false);
setDataOne(result1);
setDataTwo(result2);
console.log(data);
};
You can use Promise.all. Read more here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all.
const getData = () => {
setLoading(true);
Promise.all([fetch('api-1'), fetch('api-2')]).then(results => {
setDataOne(results[0]);
setDataTwo(results[1]);
}).finally(() => setLoading(false));
}
Utilize .flat() to reformat the data array returned from the Promise.all() into your state which holds the response obj/array,
Promise.all(
urls.map(url =>
fetch(url).then(e => e.json())
)
).then(data => {
finalResultState = data.flat();
});