Connecting a Backend & DB

김민경·2023년 2월 8일
0

FE(WEB) - React

목록 보기
11/13

🎈 How do React Apps Interact with DB?

Browser-side apps don't directly talk to databases

🎈 Sending Http Requests & Using Responses

API : Application Programming Interface
(REST or GraphQL APIs - two different standards for how a server should expose its data)

sending GET requests

function App() {
	const [movies, setMovies] = useState([]);

	// sending a HTTP request is an asynchronous task
	function fetchMovieHandler() {
    	fetch('https://swapi.dev/api/films/');
        // default method is GET
        // fetch returns a promise
        .then(response => {
        	// response object which we get has a built-in method
            // which will automatically translate this JSON response body
            // to a real Javascript object
            retutn response.json();
            // this returns a promise also
        }).then(data => {
        	const transformedMovies = data.results.map(movieData =>
            	return {
                	id : movieData.episode_id,
                    title : movieData.title,
                    openingText : movieData.opening_crawl,
                    relseaseDate : movieData.release_date
                };
            );
        	setMovies(transformedMovies);
        })
        // .catch() ... when handling errors
    }
    
    return (
    	<React.Fragment>
        	<button onClick = {fetchMoviesHandler}>Fetch Movies</button>
        </React.Fragment>
    )
}

using async/await

async function fetchMoviesHandler() => {
	const response = await fetch('https://swapi.dev/api/films/');
    const data = await response.json();
    
    const transformedMovies = data.results.map(movieData =>
    	return {
        	id : movieData.episode_id,
            title : movieData.title,
            openingText : movieData.opening_crawl,
            relseaseDate : movieData.release_date
        };
     );
     setMovies(transformedMovies);
}

sending POST requests

const movie = {
	title : titleRef.current.value,
    openingText : openingTextRef.current.value,
    releaseDate : releaseDateRef.current.value,
}
async function addMovieHandler(movie) {
	const response = await fetch('the api url',{
    	method : 'POST',
        body : JSON.stringify(movie),
        headers : {
        	'Content-Type' : 'application/json'}
        }
    });
    // can also apply try-catch syntax!
    const data = await response.json();
    console.log(data);
}

🎈 Handling Loading State & Errors

Loading while fetching data(with states)

function App() {
	const [movies, setMovies] = useState([]);
	⭐ const [isLoading, setIsLoading] = useState(false);
    
	async function fetchMoviesHandler() => {
    	⭐ setIsLoading(true);
    	const response = await fetch('https://swapi.dev/api/films/');
    	const data = await response.json();
    
    	const transformedMovies = data.results.map(movieData =>
    		return {
        		id : movieData.episode_id,
            	title : movieData.title,
            	openingText : movieData.opening_crawl,
            	relseaseDate : movieData.release_date
         	};
    	);
    	setMovies(transformedMovies);
        ⭐ setIsLoading(false);
	}
    
    return (
    	<React.Fragment>
        <section>
        	<button onClick = {fetchMoviesHandler}>Fetch Movies</button>
        </section>
        <section>
        	⭐ {!isLoading && movies.length > 0 
            && <MoviesList movies = {movies} />}
            ⭐ {!isLoading && movies.length === 0
            && <p>Found no movies.</p>}
            ⭐ {isLoading && <p>Loading...</p>}
        </section>
        </React.Fragment>
    )
}

Handling with errors

function App() {
	const [movies, setMovies] = useState([]);
	const [isLoading, setIsLoading] = useState(false);
    const [error, setError] = useState(null);
    
	async function fetchMoviesHandler() => {
    	setIsLoading(true);
        setError(null); 
        ⭐ try {
        	// wrong api 주소
        	const response = await fetch('https://swapi.dev/api/film/');
            // *the response also has a "status" field
            // which holds the concrete response status code
            
            // Unlike Axios, in fetch API, we have to manually throw an Error
            ⭐ if(!response.ok) {
            	throw new Error('Something went wrong!');
            }
            
    		const data = await response.json();
    
    		const transformedMovies = data.results.map(movieData =>
    			return {
        			id : movieData.episode_id,
            		title : movieData.title,
            		openingText : movieData.opening_crawl,
            		relseaseDate : movieData.release_date
         		};
    		);
    		setMovies(transformedMovies);
        } ⭐ catch (error) {
        	setError(error.message);
        }
        setIsLoading(false);
	}
    
    let content = <p>Found no movies.</p>;
    
    if (movies.length > 0) {
    	content = <MoviesList movies = {movies} />;
    }
    
    if (error) {
    	content = <p>{error}</p>;
    }
    
    if (isLoading) {
    	content = <p>Loading...</p>;
    }
    
    return (
    	<React.Fragment>
        <section>
        	<button onClick = {fetchMoviesHandler}>Fetch Movies</button>
        </section>
        <section>
        	{content}
        </section>
        </React.Fragment>
    )
}

🎈 using useEffect for fetching data

function App() {
	const [movies, setMovies] = useState([]);
	const [isLoading, setIsLoading] = useState(false);
    const [error, setError] = useState(null);
    
	const fetchMoviesHandler = ✨ useCallback(async () => {
    	setIsLoading(true);
        setError(null); 
        try {
        	const response = await fetch('https://swapi.dev/api/films/');
            if(!response.ok) {
            	throw new Error('Something went wrong!');
            }
            
    		const data = await response.json();
    
    		const transformedMovies = data.results.map(movieData =>
    			return {
        			id : movieData.episode_id,
            		title : movieData.title,
            		openingText : movieData.opening_crawl,
            		relseaseDate : movieData.release_date
         		};
    		);
    		setMovies(transformedMovies);
        } catch (error) {
        	setError(error.message);
        }
        setIsLoading(false);
	}, []);
    
    // should put all things that useEffect function is dependent of
    // here, it is fetchMovieHandler
    // the function could change when we use external state in the function
    // but the function will change every time the App component re-renders
    // because it is a reference type(object)
    // and this process will lead to an infinite loop
    // ✨-> use useCallback
   
    ⭐ useEffect(() => {
    	fetchMovieHandler();
    }, [fetchMovieHandler]);
    
    // since in the useEffect function it cannot return a promise
    // (cannot use async/await in the useEffect function directly)
    // , indirectly call a function which contains async/awiat function
    
    let content = <p>Found no movies.</p>;
    
    if (movies.length > 0) {
    	content = <MoviesList movies = {movies} />;
    }
    
    if (error) {
    	content = <p>{error}</p>;
    }
    
    if (isLoading) {
    	content = <p>Loading...</p>;
    }
    
    return (
    	<React.Fragment>
        <section>
        	<button onClick = {fetchMoviesHandler}>Fetch Movies</button>
        </section>
        <section>
        	{content}
        </section>
        </React.Fragment>
    )
}
profile
🏛️❄💻😻🏠

0개의 댓글