React
20210610 React09 : 컴포넌트간 통신(상하, 하상), Context API & useContext(데이터 set, 데이터 get 3가지 방식/Cunsumer, Class static, Function useContext)
React 09
컴포넌트 간 통신
하위 컴포넌트 변경 하기
- 예시
- 상위 컴포넌트에서 하위 컴포넌트에서 쓰이는 state의 값을 변경 하는 경우
- A컴포넌트(버튼) -> B컴포넌트 -> C컴포넌트 -> D컴포넌트 -> E컴포넌트(pros.value)
- A에 있는 버튼을 클릭해서 E컴포넌트에 있는 value를 변경하는 것
- 상위 컴포넌트의 state 값을 props로 내려서 변경함
import { useState } from "react";
export default function A() {
const [value, setValue] = useState("아직 안바뀜");
return (
<div>
<B value={value} />
<button onClick={click}>E의 값을 바꾸기</button>
</div>
);
function click() {
setValue("E의 값을 변경");
}
}
function B({ value }) {
return (
<div>
<p>여긴 B</p>
<C value={value} />
</div>
);
}
function C({ value }) {
return (
<div>
<p>여긴 C</p>
<D value={value} />
</div>
);
}
function D({ value }) {
return (
<div>
<p>여긴 D</p>
<E value={value} />
</div>
);
}
function E({ value }) {
return (
<div>
<p>여긴 E</p>
<h3>E에 있는 값 : {value}</h3>
</div>
);
}
상위 컴포넌트를 변경하기
- 예시
- 하위 컴포넌트에서 상위 컴포넌트의 값을 변경하는 경우
- E컴포넌트(버튼) -> D컴포넌트 -> C컴포넌트 -> B컴포넌트 -> A컴포넌트(pros.value)
- 상위 컴포넌트의 state 변경하는 함수 자체를 props로 전달하여 하위 컴포넌트로 내려서 하위 컴포넌트에서 state 값을 변경함
export default function A() {
const [value, setValue] = useState("아직 안바뀜");
//setValue를 그대로 전달해도 되고, setValue를 실행하는 함수를 만들어서 전달해도 됨
return (
<div>
<p>A에 있는 값 : {value}</p>
<B setValue={setValue} />
</div>
);
}
function B({ setValue }) {
return (
<div>
<p>여긴 B</p>
<C setValue={setValue} />
</div>
);
}
function C({ setValue }) {
return (
<div>
<p>여긴 C</p>
<D setValue={setValue} />
</div>
);
}
function D({ setValue }) {
return (
<div>
<p>여긴 D</p>
<E setValue={setValue} />
</div>
);
}
function E({ setValue }) {
const click = () => {
setValue("A의 값을 변경!");
};
return (
<div>
<p>여긴 E</p>
<button onClick={click}>A의 값 바꾸기</button>
</div>
);
}
결론
- 둘다, 일단 state를 공유하기 위해서는 상위 컴포넌트에서 state를 정의하여야 한다.
- state 값을 변경하는것을 공유하거나, state 값을 표현하기 위해 공유하는 작업에서
- 상위 컴포넌트에서 정의된 state를 하위 컴포넌트가 값을 변경하는 경우면
setState 함수를 내리고
- 상위 컴포넌트에서 정의된 state를 하위 컴포넌트에서 값을 표현하는 경우면
state 자체를 내림
- component가 복잡해 질수록 이러한 state를 props을 통해 내려 보내는 작업에 주의를 기울여야함
Context API & useContext
- context 또한 react에 내장되어 있는 API 임
- react : context API
- 컴포넌트 간에 데이터를 공유하는 경우 props를 계속 전달해줘야 하는 과정이 번거러움,
- 그래서 context API를 통해 props로 넘겨주지 않아도 많은 컴포넌트가 여러한 값을 공유하도록 할 수 있음
하위 컴포넌트 전체에 데이터를 공유하는 법
- 데이터를 set하는 놈
- 가장 상위 컴포넌트 -> provider (프로바이더)로 가장 상위 컴포넌트를 감싸서 사용
- 데이터를 get하는 놈
- 모든 하위 컴포넌트에서 접근 가능
- consumer(컨슈머)로 하는 방법
- class 컴포넌트의 this.context로 하는 방법
- funcitonal 컴포넌트의 useContext로 하는 방법
- 모든 하위 컴포넌트에서 접근 가능
데이터를 set 하기
- 컨텍스트 생성하기 -> 컨텍스트.프로바이더 사용 -> value를 사용
// PersonContext.js
import React from "react";
const PersonContext = React.createContext();
export default PersonContext;
// index.js
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import PersonContext from "./contexts/PersonContext";
const persons = [
{ id: 0, name: "kim", age: 24 },
{ id: 1, name: "park", age: 35 },
];
ReactDOM.render(
<React.StrictMode>
<PersonContext.Provider value={persons}>
{/*provider 하위에 있는 컴포넌트가 모두 공유하는 데이터를 설정할 수 있음 */}
<App />
</PersonContext.Provider>
</React.StrictMode>,
document.getElementById("root")
);
데이터를 get 하기 01 : Consumer 방식
- class, function 모두 범용적으로 사용할 수 있는 방식
- context를 가져온다 -> context.consumer를 사용한다. -> value를 사용함
//Ex01.jsx
// context가져오기
import PersonContext from "../contexts/PersonContext";
export default function Example1() {
return (
// Consumer 사용해서 안에 함수를 넣어 공유하기로 한 값을 활용해서 Example1 컴포넌트가 render할 부분을 꾸민다.
<PersonContext.Consumer>
{(persons) => (
<ul>
{persons.map((person) => (
<li>{person.name}</li>
))}
</ul>
)}
</PersonContext.Consumer>
);
}
import logo from "./logo.svg";
import "./App.css";
import Example1 from "./components/Ex01";
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<Example1 />
</header>
</div>
);
}
export default App;
데이터를 get 하기 02 : class component 방식 (비추천)
- static contextType에 context를 설정 -> this.context = value 임
- 단점:
static contextType
의 경우 여러가지를 지정할 수 없음- persons 말고 다른 데이터를 동시에 가져와서 사용하는 경우 사용이 불가함
import React from "react";
// context 가져오기
import PersonContext from "../contexts/PersonContext";
export default class Example2 extends React.Component {
// contextType 을 static으로 넣어 Context를 연결
static contextType = PersonContext;
render() {
// this.context가 해당 값을 의미
// [
// { id: 0, name: "kim", age: 24 },
// { id: 1, name: "park", age: 35 },
// ];
// persons 변수로 받아와 사용
const persons = this.context;
return (
<ul>
{persons.map((person) => (
<li>{person.name}</li>
))}
</ul>
);
}
}
// static contextType 코드 부분을 대체할 수 있음
// Example2.contextType = PersonContext;
데이터를 get 하기 03 : function component 방식 (추천)
- useContext 훅 으로 context를 인자로 호출 -> useContext의 return이 value 임
- 여러가지 context를 가져다 사용할 수 도 있음
import { useContext } from "react";
// Context 가져오기
import PersonContext from "../contexts/PersonContext";
export default function Example3() {
// Context uesContext에 넣어 연결하고, 해당 값 가져오기
const persons = useContext(PersonContext);
return (
// 값 사용하기
<ul>
{persons.map((person) => (
<li>{person.name}</li>
))}
</ul>
);
}