I need to make two separate api calls in the same react component. However, I’m having trouble getting information when I try to use it in my HTML. Specifically the similar data in this code.
function Info() {
let params = useParams();
const [details, setDetails] = useState({});
const [similar, setSimilar] = useState({});
const [activeTab, setActiveTab] = useState('instructions')
const fetchDetails = async () => {
const data = await fetch(`https://api.spoonacular.com/recipes/${params.name}/information?apiKey=${process.env.REACT_APP_API_KEY}`)
const detailData = await data.json();
setDetails(detailData);
console.log(detailData);
};
const fetchSimilar = async () => {
const data = await fetch(`https://api.spoonacular.com/recipes/${params.name}/similar?apiKey=${process.env.REACT_APP_API_KEY}`)
const similarData = await data.json();
setSimilar(similarData);
console.log(similarData);
};
useEffect(() => {
fetchDetails();
fetchSimilar();
}, [params.name]);
return (
<DetailWrapper>
<div>
<h2>{details.title}</h2>
<img src={details.image} alt={details.title} />
</div>
<InfoDiv>
<Button className={activeTab === 'instructions' ? 'active' : ''} onClick={() => setActiveTab('instructions')}>Instructions</Button>
<Button className={activeTab === 'ingredients' ? 'active' : ''} onClick={() => setActiveTab('ingredients')}>Ingredients</Button>
{activeTab === 'instructions' && (
<div>
<p dangerouslySetInnerHTML={{__html: details.summary}}></p>
<p dangerouslySetInnerHTML={{__html: details.instructions}}></p>
</div>
)}
{activeTab === 'ingredients' && (
<ul>
{details.extendedIngredients.map((ingredients) => (
<li key={ingredients.id}>{ingredients.original}</li>
))}
</ul>
)}
</InfoDiv>
<div>
<p>{similar.title}</p>
</div>
</DetailWrapper>
)
}
ferent way I should be making multiple calls in one file? Should I fetch both url data in one function instead of two?
I already tried to make a separate component which holds the data I need however I still got the same results. This leads me to believe that its just how I’m calling this request.
2
Answers
Putting the function call inside
useEffect
with the params in the dependency means that the functions are only called when theparams.name
changes. If they are not being called, then the issue may be due toparams.name
not changing. Try it with an empty array to see if the data is fetched once, before adding the dependency. That way you can tell if the issue is with the dependency or the function call itself.The issue with your code is that you are setting the state of
similar
anddetails
to an empty object{}
initially, and then trying to access properties of these object in your HTML before the API call has returned and updated the state. Therefore, you are not seeing any data from the similar API call in your HTML.To resolve this issue, you can use an optional chain operator
?
before invoking any keys from thesimilar
anddetails
objects. This will safeguard against anynull
orundefined
values that may exist before the API calls return and update the state. For instance:or you can add a check in your HTML to only render the similar data if it exists.
Regarding your question about making multiple API calls in one file, your current approach of using separate functions to fetch each API endpoint and calling them both in the
useEffect
hook is a valid approach. Fetching both URLs in one function would also work, but might not be necessary unless you need to coordinate the results of both calls in some way.