Context API 란?
- React 컴포넌트 트리 전체에서 데이터를 공유할 수 있는 방법을 제공
- 부모자식간 관계가 중첩된 구조에서 데이터를 전달하는데 있어 불필요한
props drilling (상태 내리꽂기)을 방지함- 사용하기 위해서 useContext hook 필요함
- React에 기본적으로 내장됨
Context API를 사용하려면 객체가 필요
React.createContext() : Context 객체를 생성 시 사용하는 함수
- Context : react에서 컴포넌트 계층 구조를 통해 데이터를 효율적으로 전달하기 위한 메커니즘 (작동원리 / 방식)
- Provider : 데이터를 제공 (Exam6)
- Consumer : 데이터를 소비 (Child3)
- Context.Provider : 하위 컴포넌트에게 데이터를 전달할 때 (제공할 때) 사용
import { createContext, useContext, useState } from "react"; const UserContext = createContext(); // import 해줘야 함 // 부모 컴포넌트 const Exam6 = () => { const [user, setUser] = useState("홍길동"); // Context.Provider : 하위 컴포넌트에게 데이터를 전달할 때 (제공할 때) 사용 return ( <UserContext.Provider value={{ user, test: "test값 입니다." }}> <h1>부모 : 부모가 가진 상태 값 {user}</h1> <Child1 /> </UserContext.Provider> ); }; const Child1 = () => { return ( <> <h1>Child1</h1> <Child2 /> </> ); }; const Child2 = () => { const contextValue = useContext(UserContext); return ( <> <h1> Child2 : {contextValue.user} / {contextValue.test} </h1> <Child3 /> </> ); }; const Child3 = () => { // Exam6가 가진 user 상태 값을 사용하고 싶다! const contextValue = useContext(UserContext); // Context로 등록된 객체 중 이름이 UserContext를 꺼내어 return ( <> <h1> Child3 : {contextValue.user} / {contextValue.test} </h1> </> ); }; export default Exam6;
<UserContext.Provider value={ {user, test : "test값 입니다."}}>1개의 데이터는 value={ }, 여러개는 k:v 꼴로 {} 추가해서 나열하기
React(프론트 : 클라이언트) - JS 요청 (비동기)
SpringBoot(백엔드 : 서버) - DB 조회 후 반환CORS (Cross Origin Resource Sharing) Error
Origin(url) :
http://localhost:5173
http://localhost:80
서로 포트가 달라도 서로 사용하도록 허락 (어노테이션으로)
@CrossOrigin : Spring에서 제공하는 어노테이션으로 CORS 설정을 위해 사용됨
CORS (Cross-Origin Resource Sharing)
-> 클라이언트와 서버가 서로 다른 출처(origin)에서 요청을 주고 받을 때 발생하는 보안 정책
-> 브라우저에서는 기본적으로 다른 출처(도메인, 프로토콜, 포트)의 요청을 차단함
server
@CrossOrigin(origins = "http://localhost:5173") // 이 http를 허용함 @RestController public class MyAppController { @GetMapping("getPortNumber") public List<String> getPortNumber() { return Arrays.asList("서버포트는 80", "클라이언트 포트는 5173"); } @PostMapping("getUserInfo") public String getUserInfo(@RequestBody Map<String, Object> map) { // message 리턴 // 만약에 요청데이터 중 name값이 홍길동이고, age값이 20이면 // "홍길동 님은 20세 입니다" 리턴 // 같지 않다면 "데이터가 없습니다" 리턴 System.out.println(map.get("name")); System.out.println(map.get("age")); String message = "데이터가 없습니다."; if(map.get("name").equals("홍길동") && map.get("age").equals("20")) { message = "홍길동 님은 20세 입니다."; } return message; } }
client
import { useState } from "react"; const Exam7 = () => { const [portMsg, setPortMsg] = useState(null); // 비동기 요청할 때 띄우려고 const [userMsg, setUserMsg] = useState(""); // String 형태라 "" const getPortNumber = () => { fetch("http://localhost/getPortNumber") // 오리진이 달라서 http:// .then((res) => res.json()) // List로 넘어와서 .then((data) => { setPortMsg(data); }); }; const getUserInfo = () => { fetch("http://localhost/getUserInfo", { method: "post", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: "홍길동", age: "20" }), }) .then((res) => res.text()) .then((data) => setUserMsg(data)); }; return ( <div> <p>1. 서버로부터 응답 받은 값(GET)</p> <button onClick={getPortNumber}>GET 요청 보내기</button> <ul> {portMsg?.map((msg, idx) => ( <li key={idx}>{msg}</li> // ? : 안전탐색연산자 - null이면 무시, null이 아니면 넘어가기 ))} </ul> <p>2. 서버로 값 전달 후 응답 받은 값(POST)</p> <button onClick={getUserInfo}>POST 요청 보내기</button> <p>{userMsg}</p> </div> ); }; export default Exam7;