[React] 리액트 context, ref, 훅

cool_kim·2021년 7월 12일
0

React

목록 보기
5/8
post-thumbnail

리액트 context

하위 컴포넌트가 상위 컴포넌트에서 상당히 멀리 떨어져 있을때 사용

📍 기계적으로 속성값을 전달하는 코드

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에서 그 값을 받아 처리 가능

  • Provider 컴포넌트의 값이 변경 되면 하위 모든 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 컴포넌트 밖에서 자식 컴포넌트를 렌더링 되면 상태값이 변하지 않음


ref

: 자식 요소에 직접 접근하기

📍 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

    • 렌더링과 상관없는 값을 저장할 때 유용하게 사용 (setTimeout)
  • useMemo

    • 메모이제이션 기능 제공
    • 계산량이 많은 함수의 반환값을 재활용하는 용도
    • const value = useMemo(() => renExpensiceJob(v1, v2), [v1, v2]);
  • useCallback

    • 메모이제이션 기능 제공 ( 함수 메모이제이션에 특화 )
    • 불필요하게 렌더링 되는 현상을 막기 위해 사용
    • const onSave = useCallback(() => saveToServer(name, age), [name, age])
  • useReducer

    • 여러개의 상태값을 하나의 훅으로 관리
    • 반환 값 : 상태값 & dispatch함수
    • const [state, dispatch] = useReducer(reducer, INITIAL_STATE);
    • context의 Provider를 사용해서 dispatch 함수 내려 보내 줄 수 있음
  • useImperativeHandle

    • 함수가 반환하는 값이 부모의 ref객체가 참조하는 값이 됨
  • useLayoutEffect

    • 부수효과 함수를 동기로 호출 → 렌더링 결과가 돔에 반영된 직후에 바로 호출
    • 이 훅 안에서 연산을 많이 하면 브라우저 먹통이 될 수 있음
  • useDebugValue

    • 리액트 개발자 도구에 좀 더 풍부한 정보 제공 가능(디버깅할 때 편리)

      useDebugValue(
      	state === STATE_START
      		? 'start'
      		: state === STATE_RUNNING
      		? 'running'
      		: 'stop',
      };

      📍결과

profile
FE developer

0개의 댓글