Home 04-Fragments-Portals-useRef
Post
Cancel

04-Fragments-Portals-useRef

강의 링크


1. Fragments

1) 필요성

JSX 제한 사항

1
2
3
4
5
// root요소는 1개여야 한다. 
return (
    <h2>Root</h2>
    <p>ERROR!!!</p>
)
  • 자바스크립트는 둘 이상을 반환할 수 없기 때문이다.
  • 즉, 단 1개의 리액트 createElement 호출만 반환되어야 한다.


해결방안1 div로 묶기

1
2
3
4
5
6
7
// root요소는 1개여야 한다. 
return (
  <div>
    <h2>Root</h2>
    <p>ERROR!!!</p>
  </div>
)
  • 그러나 div지옥이 발생할 수 있다는 문제가 있다.


해결방안2 배열 사용하기

1
2
3
4
5
6
7
// 일반적으로 사용되지 않는 방법이다. 
return (
  [
    <h2 key="h2">Root</h2>
    <p key="p">ERROR!!!</p>
  ]
)


2) wrapper

wrapper 컴포넌트를 추가하여 위에서 언급된 문제를 해결할 수 있다.

1
2
3
4
5
6
7
// 빈 컴포넌트 이다. 
// props.children을 반환한다.
const Wrapper = props => {
  return props.children;
};

export default Wrapper;
  • JSX 요구사항을 충족하기 위해 있는 div태그의 대안으로 사용할 수 있다.
  • 빈컴포넌트이기 때문에 DOM에 아무것도 렌더링 하지 않는다.


3) Fragmentss

리액트에는 wrapper 컴포넌트인 Fragments 컴포넌트를 제공한다.

1
2
3
4
5
6
7
8
import {Frament} from "react"

return (
  <Frament>
    <h2 key="h2">Root</h2>
    <p key="p">ERROR!!!</p>
  </Frament>
)
  • Frament를 사용하면 더 깔끔한 코드를 작성할 수 있다.
  • 최종 페이지에 불필요한 HTML 요소들이 줄어든다.


2. Portals

vue3의 teleport와 유사한 개념이다.

1) 필요성

1
2
3
4
5
6
7
8
import {Frament} from "react"

return (
  <Frament>
    <MyModal />
    <MyInputForm />
  </Frament>
)
  • 기본적으로 Modal은 페이지 위에 표시되는 오버레이다.
  • 실제 DOM에 표시 될 때, 현재의 구조로는 페이지에 대한 오버레이로 인식하지는 않을 것이다.
  • ex) 스크린 리더가 렌더링되는 HTML 코드를 해석할 때 일반적인 오버레이라고 인식하지 않는다.
  • HTML문서를 보았을 때, Modal이 해당 페이지에 대한 오버레이인지를 확실히 표현해야 한다.


2) 사용법

해당 컴포넌트의 HTML 내용을 다른 곳으로 포털, 즉 이동시킬 수 있다.

1
2
3
4
5
6
7
8
9
10
import {Frament} from "react"
import {createPortal} from "react-dom"

const MyModal = (props) => {
  return(
    <Frament>
	  {createPortal(렌더링 되어야 하는 노드, 렌더링 되어야할 실제 DOM 컨테이너)}
    </Frament>
  )
}
  • 포털에는 두 가지가 필요하다.
    • 컴포넌트를 이동시킬 장소
    • 컴포넌트에게 그 곳에 포털을 가져야 한다고 알려줘야 한다.
  • createPortal 메서드는 2개의 인수를 취한다.
    • 렌더링 되어야 하는 리액트 노드
    • 포인터 (렌더링 되어야 하는 실제 DOM 컨테이너) => document.getElementById()로 접근할 수 있다.


3. useRef

직접 DOM 요소에 접근하여 작업할 수 있다.

공식문서

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// state 없이 input 다루기

import React, { useState, useRef } from 'react';

import Card from '../UI/Card';
import Button from '../UI/Button';
import Wrapper from '../Helpers/Wrapper';
import classes from './AddUser.module.css';

const AddUser = (props) => {
  const nameInputRef = useRef();
  const ageInputRef = useRef();

  const addUserHandler = (event) => {
    event.preventDefault();
    const enteredName = nameInputRef.current.value;
    const enteredUserAge = ageInputRef.current.value;
      
    props.onAddUser(enteredName, enteredUserAge);
    nameInputRef.current.value = '';
    ageInputRef.current.value = '';
  };

  return (
    <Wrapper>
      <Card className={classes.input}>
        <form onSubmit={addUserHandler}>
          <label htmlFor="username">Username</label>
          <input id="username" type="text" ref={nameInputRef} />
          <label htmlFor="age">Age (Years)</label>
          <input id="age" type="number" ref={ageInputRef} />
          <Button type="submit">Add User</Button>
        </form>
      </Card>
    </Wrapper>
  );
};

export default AddUser;
  • ref의 반환 값은 객체로 current속성을 가지고 있다.
    • current 속성에 연결된 실제 DOM 노드를 가져온다.
    • 해당 노드를 조작, 작업할 수 있다.
  • 리액트 없이 DOM을 조작할 수 있다.
    • ref로 제어되는 컴포넌트는 리액트로 제어되지 않는 컴포넌트라고 부른다.
  • 주로 노드 참조 목적으로 사용되지만, 컴포넌트 렌더링에 영향을 끼치지 않는 값을 참조하기 위해 사용된다.
    • useState와 달리 current 값이 변경되어도 컴포넌트가 다시 렌더링되지 않는다.
    • 불필요한 렌더링을 방지하여 성능을 최적화 할 수 있다.


This post is licensed under CC BY 4.0 by the author.