Frontend/Study

[React] React 완벽 가이드 섹션 9 : 프레그먼트 작업, Portals & Ref

BeNI 2022. 5. 2. 03:05
728x90

https://www.udemy.com/course/best-react/


1. jsx 제한 사항 및 해결 방법

- 루트 요소는 1개여야만 한다

- 그 이유는 자바스크립트 자체가 원래 하나의 요소만 반환하기 때문

// 자바스크립트에서 아래 문법은 불가능 하다
return (
  React.createElement('h2',{}, 'hi');
  React.createElement('h2',{}, 'hi');
);

 

1) 해결 방법

ⓐ 여러개의 요소를 하나의 <div>태그(아무태그)로 감싼다. => div soup 발생, 불필요한 렌더링 과정 실행

* div soup : div태그가 중첩되어 스타일링이 깨질 수도 있고, 속도가 느려질 수도 있다.

ⓑ 배열형태로 반환한다. => 경고 발생  키가 필요하기 때문

 

그래서 이상적인 해결방법?

👉 Wrapper 컴포넌트 생성. 단지 children만을 반

const Wrapper = (props) => {
  return props.children;
}

export default Wrapper;

사실 생성할 필요는 없다. 리액트에서 제공하기 때문

return (
    <React.Fragment>
    	...
    </React.Fragment>
)
return (
    <>
    	...
    <>
)

위 두가지 방식중 하나를 쓰면 된다. (실제 html요소를 dom에 렌더링 하지 않음)

 

 

2. Portals

- 오버레이 안에 있는 모달이 깊게 중첩되는 문제를 해결하기위해 나온 개념

- modal 컴포넌트는 html요소의 가장 위에 오도록 해야된다... 

why? 모달은 전체 페이지에 대한 오버레이이다. 그리고 스타일링이나 접근성 관점에서 문제 발생 우려 

 

>> html에서 컴포넌트의 코드위치를 조정할 수 있다 ! ! 

 

1) 사용 방법

2개가 필요 : 컴포펀트를 이동시킬 장소, 컴포넌트에게 그곳에 포털을 가져야 한다고 알려줘야 함

 

- index.html에서 div태그 구조를 만들어 준다. (index.html이 아니어도 상관없다 ! portal 시킬 장소)

...
<body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="backdrop-root"></div>
    <div id="overlay-root"></div>
    <div id="root"></div>
</body>
...

 

- 끌어올릴 컴포넌트에서 리액트 돔을 불러온다. (react18에서는 react-dom/client)

import ReactDOM  from "react-dom";

- createPortal을 이용하여 컴포넌트를 끌어올린다.

return(
    <> {ReactDom.createPortal( jsx요소, 끌어올릴 위치} </>
    // ReactDom.createPortal(<Error />, document.getElementById('backdrop-root'))
);

모달을 작성한 코드 위치에 상관 없이 내가 지정한 위치로 이동하여 렌더링 된다.

 

 

3. ref

- 실제 dom요소에 접근하여 그것들로 작업할 수 있도록 해주는 것

- 하지만 dom의 요소들을 변경하는 것은 지양해야한다. 보통은 값을 빠르게 읽어오고 싶을 때 사용 !

 

useRef는 하나의 객체를 반환하는데, 그 객체는 current라는 속성을 갖고 있다.

current는 ref랑 연결된 실제 값을 가진다. 기본 값은 useRef()안 정의된 초기값이지만

코드가 실행된 후에는 연결된 dom 요소 가지게 된다.

 

 

 

 

1) 사용 방법

- useRef를 import 한다.

import { useRef } from "react";

- ref로 받아올 변수 선언

const nameInputRef = useRef();
const ageInputRef = useRef();

- form 태그에서 ref로 dom 요소를 접근시에 아래처럼 사용

<form onSubmit={addUserHandler}>
    <input id="username" type="text" ref={nameInputRef} />
    <input id="age" type="number" ref={ageInputRef} />
    <Button type="submit">Add User</Button>
</form>

- ref로 선언한 변수는 객체를 반환한다. 

  그리고 변수이름.current.(실제 돔에서 사용되는 속성) 으로 접근 가능

const enteredName = nameInputRef.current.value;
const enteredUserAge = ageInputRef.current.value;

// 초기화 (dom에 직접 접근)
nameInputRef.current.value = '';
ageInputRef.current.value = '';

- 위와 같이 실제 돔의 input.value 속성을 가져와서 사용 가능하다.

 

- state나 ref 둘 중 적합한 방식으로 선택하여 사용하면 된다.

- 단순히 값을 읽는 행위는 state를 이용하지 않는게 낫다.  ref를 이용하여 dom에 접근하는게 낫다.

 

* 제어되는 컴포넌트와 제어되지 않는 컴포넌트

- ref로 읽어온 값을 이용하는 컴포넌트는 react의 ref의 기능을 이용하는 것이지 제어되는 컴포넌트는 아니다..

- 해당 컴포넌트는 내부 state이기 때문에 내부 값들은 리액트에 의해 제어되지 않는다.

-  ref를 이용해서 단지 가져오는 것에 불과

- input 요소는 브라우저에 의해 내부 state를 갖는 경향이 있다.

- 만약 value를 react state를 이용해 관리한다면 제어되는 컴포넌트라 할 수 있다.

 

 

728x90