컴포넌트에서 context를 읽고 구독할 수 있게 해주는 React Hook
useContext는 호출하는 컴포넌트에 대한 context 값을 반환함
위 값은 호출한 컴포넌트에서 트리상 가장 가까운 SomeContext.Provider에 전달된 value
이런 provider가 없을 경우에는 반환되는 값은 createContext에 전달한 defaultValue가 됨
동일한 컴포넌트에서 반환된 provider의 영향을 받지 않음을 주의
context를 업데이트 하려면?
function MyPage() {
const [theme, setTheme] = useState('dark');
return (
<ThemeContext.Provider value={theme}>
<Form />
<Button onClick={() => {
setTheme('light');
}}>
Switch to light theme
</Button>
</ThemeContext.Provider>
);
}
import { createContext, useContext } from 'react';
const ThemeContext = createContext(null);
export default function MyApp() {
return (
<ThemeContext.Provider value="dark">
<Form />
</ThemeContext.Provider>
)
}
function Form() {
return (
<Panel title="Welcome">
<Button>Sign up</Button>
<Button>Log in</Button>
<ThemeContext.Provider value="light">
<Footer />
</ThemeContext.Provider>
</Panel>
);
}
function Footer() {
return (
<footer>
<Button>Settings</Button>
</footer>
);
}
function Panel({ title, children }) {
const theme = useContext(ThemeContext);
const className = 'panel-' + theme;
return (
<section className={className}>
{title && <h1>{title}</h1>}
{children}
</section>
)
}
function Button({ children }) {
const theme = useContext(ThemeContext);
const className = 'button-' + theme;
return (
<button className={className}>
{children}
</button>
);
}
import { useContext } from 'react';
import { LevelContext } from './LevelContext.js';
export default function Section({ children }) {
const level = useContext(LevelContext);
return (
<section className="section">
<LevelContext.Provider value={level + 1}>
{children}
</LevelContext.Provider>
</section>
);
}
import { useCallback, useMemo } from 'react';
function MyApp() {
const [currentUser, setCurrentUser] = useState(null);
const login = useCallback((response) => {
storeCredentials(response.credentials);
setCurrentUser(response.user);
}, []);
const contextValue = useMemo(() => ({
currentUser,
login
}), [currentUser, login]);
return (
<AuthContext.Provider value={contextValue}>
<Page />
</AuthContext.Provider>
);
}
function MyComponent() {
// ...
// 🚩 Don't write a ref during rendering
// 🚩 렌더링 중에 ref를 작성하지 마세요.
myRef.current = 123;
// ...
// 🚩 Don't read a ref during rendering
// 🚩 렌더링 중에 ref를 읽지 마세요.
return <h1>{myOtherRef.current}</h1>;
}
function MyComponent() {
// ...
useEffect(() => {
// ✅ You can read or write refs in effects
// ✅ Effect에서 ref를 읽거나 쓸 수 있습니다.
myRef.current = 123;
});
// ...
function handleClick() {
// ✅ You can read or write refs in event handlers
// ✅ 이벤트 핸들러에서 ref를 읽거나 쓸 수 있습니다.
doSomething(myOtherRef.current);
}
// ...
}
import { useRef } from 'react';
export default function CatFriends() {
const listRef = useRef(null);
function scrollToIndex(index) {
const listNode = listRef.current;
// This line assumes a particular DOM structure:
// 다음 코드는 특정 DOM 구조를 가정합니다.
const imgNode = listNode.querySelectorAll('li > img')[index];
imgNode.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
inline: 'center'
});
}
return (
<>
<nav>
<button onClick={() => scrollToIndex(0)}>
Tom
</button>
<button onClick={() => scrollToIndex(1)}>
Maru
</button>
<button onClick={() => scrollToIndex(2)}>
Jellylorum
</button>
</nav>
<div>
<ul ref={listRef}>
<li>
<img
src="https://placekitten.com/g/200/200"
alt="Tom"
/>
</li>
<li>
<img
src="https://placekitten.com/g/300/200"
alt="Maru"
/>
</li>
<li>
<img
src="https://placekitten.com/g/250/200"
alt="Jellylorum"
/>
</li>
</ul>
</div>
</>
);
}
https://codesandbox.io/s/41fboj?file=%2FApp.js&utm_medium=sandpack
위 코드 예제를 한번 만들어보면 좋을듯.
function Video() {
const playerRef = useRef(new VideoPlayer());
// ...
위와 같이 했을때 불필요한 렌더링 발생할 수 있음.
ref 초기화를 다음과 같이 하기
function Video() {
const playerRef = useRef(null);
if (playerRef.current === null) {
playerRef.current = new VideoPlayer();
}
// ...