
- Shared State 예제 (Props로 State 공유)
import React, {useState} from 'react';
function DoubleDisplay( {value} ) {
return (
<div>
<span>자식 A(x2) : {value * 2}</span>
</div>
);
}
function TripleDisplay({value}) {
return (
<div>
<span>자식 B(x3) : {value * 3}</span>
</div>
);
}
export default function ShareState() {
const [value, setValue] = useState(0);
const handleChange = (e) => {
setValue(Number(e.target.value));
};
return (
<div>
부모 컴포넌트
<input type='number' value={value}
onChange={handleChange} />
<DoubleDisplay value={value} />
<TripleDisplay value={value} />
</div>
);
}
return에서 값을 공유한다

CFApp.jsx
import React, {useState} from "react";
function ConponentC({ temp, changeTemp}) {
return (
<div>
<span>단위(섭씨) :</span>
<input type='number' value={temp}
onChange={ (e) => changeTemp(e.target.value)} />
</div>
);
}
function ComponentF({ temp, changeTemp }) {
return (
<div>
<span>단위(화씨) : </span>
<input type='number' value={temp}
onChange={ (e) => changeTemp(e.target.value)} />
</div>
);
}
export default function CFApp() {
const [temperature, setTemperature] = useState(0);
const [type, setType] = useState('c');
const toFahrenheit = (celsius) => { // 섭씨 -> 화씨
return ((celsius * 9) / 5 + 32).toFixed(1);
}
const toCelsius = (fahrenheit) => { // 화씨 -> 섭씨
return( ((fahrenheit -32) * 5) / 9).toFixed(1);
}
const handleCilsiusChange = (temp) => {
setTemperature(temp);
setType('c');
};
const handleFahrenheitChange = (temp) => {
setTemperature(temp);
setType('f');
};
const celsius = type == 'c' ?
temperature : toCelsius(temperature);
const fahrenheit = type == 'f' ?
temperature : toFahrenheit(temperature);
return (
<div>
<h2>온도 변환</h2>
<ConponentC temp={celsius} changeTemp={handleCilsiusChange} />
<ComponentF temp={fahrenheit} changeTemp={handleFahrenheitChange} />
</div>
);
}
toFixed(1) - 소수점 1번 째 자리까지 반올림 후 String형으로 반환

기존 리액트에서 사용되는 전달 방식
- 컴포넌트 간 데이터 전달 방식
- 리액트 컴포넌트 사이에서 props를 통해 데이터를 전달하는 방식




- Context 객체를 구독하고 있는 컴포넌트를 렌더링할 때,
트리 상위에서 가장 가까이에 있는 상위 레벨의 Provider로부터 현재값을 읽음
- 상위 레벨에 매칭되는 Provider가 없을 경우 defaultValue 사용.
- Provider 없이 컴포넌트를 독립적으로 테스트할 때 유용
- defaultValue를 undefined로 설정하면 구독 컴포넌트에서 기본값을 사용하지 않음

- 함수 컴포넌트에서 context 구독(읽기)에 사용
- 컴포넌트의 자식은 함수(function as a child)
- 현재 context의 value를 받아서 React 노드를 반환
- value는 context의 Provider 중 가장 가까운 Provider의 value prop과 동일
- 상위 컴포넌트에 Provider가 없다면 createContext()의 defaultValue 값과 동일


import React from 'react';
const ThemeContext = React.createContext('light');
function App(props) {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
const styles = {
dark: {
background: 'gray',
color: 'white'
},
ligth: {
background: "white",
color: 'black'
}
}
function ThemedButton(props) {
return (
<ThemeContext.Consumer>
{ value => <button style={value == 'dark' ?
styles.dark : styles.ligth}>Button</button> }
</ThemeContext.Consumer>
)
}
export default App;


- 컴포넌트 트리상에서 가장 가까운 상위 Provider로부터 context의 value 값을 받아 옴
- context 값이 변경되면 변경된 값과 함께 useContext() 훅을 사용하는 컴포넌트가 재랜더링됨


ThemeContext.jsx
import React from 'react';
const ThemeContext = React.createContext();
ThemeContext.displayName = 'Theme-Context';
// .displayName - 컴포넌트의 이름을 명시적으로 설정
export default ThemeContext;
MainContent.jsx
import { useContext } from 'react';
import ThemeContext from './ThemeContext';
function MainContent(props) {
const { theme, toggleTheme, language, setLanguage } = useContext(ThemeContext);
return (
<div
style={{
width: '100vw',
height: '100vh',
padding: '1.5rem',
backgroundColor: theme == 'light' ? 'white' : 'black',
color: theme == 'light' ? 'black' : 'white',
}}
>
<p>테마 변경 웹사이트</p>
<button onClick = {toggleTheme}>테마 변경</button>
<br />
<label>
언어:
<select value={language} onChange={ (e) => setLanguage(e.target.value)}>
<option value='kor'>한글</option>
<option value='eng'>영어</option>
</select>
</label>
<p>{language == 'kor' ? "안녕하세요" : "Hello"}</p>
</div>
);
}
export default MainContent;
DarkOrLight.jsx
import { useState, useCallback } from 'react';
import ThemeContext from './ThemeContext';
import MainContent from './MainContent';
function DarkOrLight(props) {
const [theme, setTheme] = useState('light');
const [language, setLanguage] = useState('kor');
const toggleTheme = useCallback( () => {
if (theme == 'light') {
setTheme('dark');
} else if (theme == 'dark') {
setTheme('light');
}
}, [theme]);
return(
<ThemeContext.Provider value = {{ theme, toggleTheme, language, setLanguage }}>
<MainContent />
</ThemeContext.Provider>
);
}
export default DarkOrLight;
useCallback()
- 함수를메모이제이션하기 위한 hook
- useCallback() hook을 사용하지 않고 컴포넌트 내에 함수를 정의할 경우, 렌더링이 일어날 때마다 함수가 새로 정의됨
- useCallback() hook을 사용하면 특정 변수가 변경될 때만 함수를 재정의
결과 화면
