하위 컴포넌트가 상위 컴포넌트에서 상당히 멀리 떨어져 있을때 사용
📍 기계적으로 속성값을 전달하는 코드
export default function App() {
return (
<div>
<div>상단 메뉴</div>
<Profile username="mike" />
<div>하단 메뉴</div>
</div>
);
}
function Profile({ usename }) {
return (
<div>
**<Greeting username={username} />**
{/* ... */}
</div>
);
}
function Greeting({ username }) {
return <p>{`${username}님 안녕하세요`}</p>;
}
📍 context 사용시
import React, { createContext } from 'react'
const UserContext = createContext('unknown');
export default function App() {
return (
<div>
<UserContext.Provider value="mike">
<div>상단 메뉴</div>
<Profile username="mike" />
<div>하단 메뉴</div>
</UserContext.Provider>
</div>
);
}
function Profile({ usename }) {
return (
<div>
**<Greeting/>**
{/* ... */}
</div>
);
}
function Greeting({ username }) {
//...이 부분에서 username 사용할 수 없음
//사용 하고 싶으면 다음 코드 작성
const username = useContext(UserContext);
return (
<UserContext.Consumer>
{username => <p>{`${username}님 안녕하세요`}</p>}
</UserContext.Consumer>
);
}
✔️ Provider에서 value값을 넘겨 주면 Consumer에서 그 값을 받아 처리 가능
👍 데이터의 종류별로 Context를 나누면 렌더링 성능에 좋음
📍 하위 컴포넌트에서 데이터 수정하기
const UserContext = createContext({ username: 'unknown', helloCount: 0 });
const setUserContext = createContext(() => {});
export default fuction App() {
const [user, setUser] = userState({ username: 'mike', helloCount: 0 });
return (
<div>
<setUserContext.Provider value={setUser}>
<UserContext.Provider value={user}>
<Profile />
</UserContext.Provider>
</setUserContext.Provider>
</div>
);
}
⚠️ context 사용 시 주의할 점
1. Provider value값이 변경 되지 않아도 매번 불필요하게 렌더링 될 수 있음
2. Provider 컴포넌트 밖에서 자식 컴포넌트를 렌더링 되면 상태값이 변하지 않음
: 자식 요소에 직접 접근하기
📍 useRef훅 : 함수형 컴포넌트에서는 사용 불가능
export default function App() {
const inputRef = useRef();
useEffect(() => {
inputRef.current.focus();
}, []);
return (
<div>
<input type="text" ref={inputRef} />
<Box ref={inputRef} />
<button>저장</button>
</div>
);
}
⇒ current 함수는 실제 돔 요소를 가리키게 됨
📍 useImperativeHandel훅 사용하면 함수형 컴포넌트에서도 사용 가능
📍 forwardRef
const Button = React.forwardRef(function ({ onClick }, ref ) {
return (
<button onClick={onClick} ref={ref}>저장</button>
);
}
📍 useRef 시용하지 않고 ref속성값에 함수 입력하기
→ 이 함수는 해당 요소가 생성되거나 사라질 때 한번 씩 호출
ref={ref => ref && setText(INITIAL_TEXT)}
⚠️ useCallback훅 사용해서 함수 고정시키기
const setInetialText = useCallback(ref => ref && setText(INITIAL_TEXT), []);
📍 접근하고자 하는 돔 요소의 개수가 많을 때
const boxListRef = useRef({});
{BOX_LIST.map(item => {
<div
key={item.id}
ref={ref => {boxListRef.current[item.id] = ref}}
style={{
flex: '0 0 auto',
}}
>{`box_${iteml.id}`}</div>
))}
⚠️ 조건부 렌더링에 사용된 요소의 ref객체는 current속성을 검사하는 코드 필요
useState
useEffect
useContext
useRef
useMemo
const value = useMemo(() => renExpensiceJob(v1, v2), [v1, v2]);
useCallback
const onSave = useCallback(() => saveToServer(name, age), [name, age])
useReducer
const [state, dispatch] = useReducer(reducer, INITIAL_STATE);
useImperativeHandle
useLayoutEffect
useDebugValue
리액트 개발자 도구에 좀 더 풍부한 정보 제공 가능(디버깅할 때 편리)
useDebugValue(
state === STATE_START
? 'start'
: state === STATE_RUNNING
? 'running'
: 'stop',
};
📍결과