JSX는 요소가 한 요소에 의해 wrapping 되어있어야 한다.
왜? JS라는 언어의 태생적 한계 때문이다.
즉, "root" JSX 요소에는 1개만 return하거나 저장되어야하며, 다만 여러 children 요소를 가질 수 있기에 하나에 담아서 보내는 것이다.
하지만 이를 배열에 담아서 return하는 것은 괜찮다. 배열을 1개의 객체로 보기때문에
다만 또 한가지 애로사항이 있는데 바로 여기서도 봤던 key exception이다.
[단순히 배열을 return했을 때는 react입장에서는 다 똑같은 요소이기 때문에 어디에 추가해야될지 몰라 일단 제일 뒤에 추가하고 다시 코드에 맞게 재배열했다는 내용이었는데 그만큼 비효율적으로 되어버린 다는 뜻이다.]
즉, semantic하지 않게되는 것이다!
또한 궁극적으로 web application이 매우 느려질 것이다!
<React.Fragment>
를 사용해도 무방하다.<Body>
나 <div id=root>
밑이 가장 좋겠다. 그런데 이 일을 portal이 한다는 것이다.모달 컴포넌트
가 있는 .js파일에 장소를 잡아주는 컴포넌트
를 또 생성할 텐데 괜찮다. 왜냐면장소를 잡아주는 컴포넌트
는 항상 모달 컴포넌트
와 같이 보내지기 때문이다.장소를 잡아주는 컴포넌트
를 다른 컴포넌트
와 함께 쓰려면 따로 생성해두어도 된다.즉, 포탈은 렝더링된 HTML내용을 다른 곳으로 옮기는 것이다.
import React, {useState, useRef} from "react";
...
const .js이름 = props => {
const HTML과관련된변수명 = useRef();
리액트가 이 코드에 처음 도달해서 이 코드를 렌더링할 때 nameInputRef에 저장된 값을 이 인풋을 기반으로 렌더링된 네이티브 DOM 요소에 설정한다. 그럼 결과값은 무엇인가?
ref의 함수로 나온 결과값은 항상 객체이며 항상 current
라는 property를 갖고있다. 그리고 값은 렌더링된 DOM노드의 값을 갖고있다.
즉, 코드가 실행되자마자 ref property덕에 useRef와 연결되는 것이다.
그래서 실제 DOM의 값과 연결된것이기 때문에 여러가지 작업을 할 수 있다. 하지만 사실 조작하지 않는 것이 좋다. 왜? DOM은 React에 의해서만 조작되어야하기 때문에 하지만 우리는 단지 값을 읽기위해 쓰는 것이기 때문에 괜찮다!
그래서 이것을 제어되지 않는 컴포넌트(Uncontrolled component)라고 하기도 한다.
왜? react의 state에 의해서 제어되지 않기 때문에
앞서 언급했던 react의 state에 의해 제어되지 않는 컴포넌트들을 뜻한다.
이게 왜? 중요할까?
가장 일반적으로 입력 컴포넌트에 대해 이야기할 때는 <form>
컴포넌트를 사용한다.
왜냐하면 <form>
컴포넌트는 기본적으로 브라우저에 의해 내부 state를 갖는 경향이 있기 때문이다.
즉, 사용자 입력을 받아 저장하고 반영하는 인풋 요소가 구성되어 있다. 그리고 리액트 앱에서 해당 컴포넌트로 작업할 때 리액트 state를 그것에 연결하여 사용한다.
하지만 ref를 사용하면 react 작동 원리를 거스르기 때문에 리액트에서 <input>
컴포넌트로 작업할 때
제어/제어되지 않음에 대해 논하는 것이다
forward refs는 input 컴포넌트와 명령형으로 상호 작용할 수 있게 해준다.
즉, 예를 들어 어떤 state를 전달해서 그 컴포넌트에서 무언가를 변경하는 방식이 아니라
컴포넌트 내부에서 함수를 호출하는 방식으로 변경한다.
하지만 이 방법은 자주 해서 안 됩니다 왜냐하면 일반적인 리액트 패턴이 아니기 때문이다.
forward refs의 반환값은 react 컴포넌트이다.
import React, {useImperativeHandle} from "react";
const 사용자정의컴포넌트 = React.forwardRer((props, ref) => {
~~useRef()~~
})
useImperativeHadle(ref, () => {
return {};
})
useImperativeHadle(ref, 객체를 반환하는 함수)
이다.
이때 이 객체는 외부에서 사용할 수 있는 모든 데이터를 포함한다.
즉, 외부에서 객체의 key값으로 접근한다는 뜻이다. 그리고 이때 value값을 함수를 point해도 좋다.
Ref훅을 가져와 순수 HTML로 짜여있는 input 컴포넌트 함수로 들어간다. 이때 ref는 앞서 배운것처럼 uncontrolled이기 때문에 별도로 예약어인 ref
를 사용해주어야한다. 또한 useImperativeHandle
도 함께 import 해주어야한다.
마찬가지로 ref를 정의하고
focus할 수 있는 함수를 구현한다. 또한
해당 HTML에 내장 기능인 ref prop을 추가한다.
다시 로직이 구현되어있는 js로 돌아와 컴포넌트가 사용된 tag에 props를 추가해준다.
useImperativeHandle 및 forwardRef를 사용하면
리액트 컴포넌트에서 온 기능을 노출하여
부모 컴포넌트에 연결한 다음, 부모 컴포넌트 안에서
참조를 통해 그 컴포넌트를 사용하고
기능을 트리거할 수 있다