only call hooks from a React component function
from built-in hook call or custom hook

only call hooks at the top level
must call hooks before return statement, outside of loops, conditions, or nested functions

you can call multiple state or effect hooks
there can be multiple hook calls as long as they are in the same order
cannot place hook calls inside conditionals → might result in a hook being skipped when compared with previous render
compiles and runs with expected output but clicking button results in invalid hook call error

always make multiple hook calls in the same sequence
conditions for hooks have to be placed inside them

Fetch is used to make a server request to retrieve JSON data from it
Fetch API - set of functionalities to use in JS to make server requests
JavaScript Process → single-threaded execution (each step begins after previous step finishes)

Asynchronous JavaScript → delegation of duties

fetch() in action
index.html


script.js

fetching data from a third-party API is considered a side-effect → need to use useEffect for Fetch API calls in React
ex. component that fetches data from an external API to display information about a cryptocurrency
pass an anonymous function (containing data fetching code) as a call to the useEffect hook
import { useState, useEffect } from "react";
export default function App() {
const [btcData, setBtcData] = useState({});
useEffect(() => {
fetch(`https://api.coindesk.com/v1/bpi/currentprice.json`)
.then((response) => response.json())
.then((jsonData) => setBtcData(jsonData.bpi.USD))
.catch((error) => console.log(error));
}, []);
return (
<>
<h1>Current BTC/USD data</h1>
<p>Code: {btcData.code}</p>
<p>Symbol: {btcData.symbol}</p>
<p>Rate: {btcData.rate}</p>
<p>Description: {btcData.description}</p>
<p>Rate Float: {btcData.rate_float}</p>
</>
);
}
or extract the anonymous function into a separate function expression or function declaration, and then just reference it
import { useState, useEffect } from "react";
export default function App() {
const [btcData, setBtcData] = useState({});
const fetchData = () => {
fetch(`https://api.coindesk.com/v1/bpi/currentprice.json`)
.then((response) => response.json())
.then((jsonData) => setBtcData(jsonData.bpi.USD))
.catch((error) => console.log(error));
};
useEffect(() => {
fetchData();
}, []);
return (
<>
<h1>Current BTC/USD data</h1>
<p>Code: {btcData.code}</p>
<p>Symbol: {btcData.symbol}</p>
<p>Rate: {btcData.rate}</p>
<p>Description: {btcData.description}</p>
<p>Rate Float: {btcData.rate_float}</p>
</>
);
}
the response from fetching third-party data might fail, or be delayed → provide different renders based on whether or not the data has been received
ex. set up two renders, based on whether or not the data has been successfully fetched
return someStateVariable.length > 0 ? (
<div>
<h1>Data returned:</h1>
<h2>{someStateVariable.results[0].price}</h2>
</div>
) : (
<h1>Data pending...</h1>
);
fetch() + useEffect hook in action