* React Developer Tools
Vue.js Devtool처럼 리액트도 확장프로그램이 존재한다.
확장프로그램 설치 후 컴포넌트에 들어가면 컴포넌트 트리를 볼 수 있다.
컴포넌트 내부에 루트요소는 무조건 1개여야한다. <div>로 감싸는 방법 외에 할 수 있는 방법은,
const Wrapper = props => {
return props.childern;
};
export default Wrapper;
import React from './react';
import Wrapper from './Wrapper';
import Card from './Card';
const Test = () => {
return (
<Wrapper>
<Card>
</Card>
</Wrapper>
)
}
props.childern요소만을 return하는 빈 컴포넌트를 생성해서, div대신 감싸주면 된다.
이렇게 하면 빈 div로 인해 계층이 깊어지지 않음.
* React Fregment
return(
<React.Fragment>
<h2> hello </h2>
</React.Fragment>
);
return(
<>
<h2> hello </h2>
</>
);
Fragments – React
A JavaScript library for building user interfaces
ko.reactjs.org
두 구문은 빈 Wrapper를 렌더링, 실제 HTML요소를 DOM에 렌더링하지 않는다.
앞에서 말한 Wrapper와 같은 역할을 하고, <React.Fragmet>로 감싼 구문은 항상 작동하지만, <> 로 감싼 구문은 조건에 따라 작동한다.
* Portals
Portal은 랜더링된 HTML 내용을 다른 곳으로 옮기는 것.
ReactDOM.createPortal(child, container)
첫 번째 인자(child)는 엘리먼트, 문자열, 혹은 fragment와 같은 어떤 종류이든 렌더링할 수 있는 React 자식(노드)입니다. 두 번째 인자(container)는 DOM 엘리먼트(포인터: 실제로 랜더링되어야 하는 위치를 가리키는 포인터)입니다.
Portals – React
A JavaScript library for building user interfaces
ko.reactjs.org
포털에는 2가지가 필요하다.
1. 컴포넌트를 이동시킬 장소
2. 컴포넌트에게 그 장소에 포털을 가져야 한다고 알려주기
//ReactDom.createPortal(렌더링 할 수 있는 자식노드(조건: JSX코드여야함), document.getElemetById('실제 렌더링 되는 DOM주소'))
//실제 렌더링되는 DOM주소는 public내부의 index.html에 만들어놓은 <div id="backdrop-root">를 말한다.(backdrop이 렌더링되었으면 하는 위치)
//document.getElementById는 리액트와 전혀 상관이 없다. 단지 DOM노드의 위치에 접근하기 위해 브라우저에서 제공하는 API를 사용한 것일 뿐.
//이 API를 사용하여 실제 DOM요소에 접근하는 것
const ErrorModal = (props) => {
//onConfirm을 사용하는 이유는 Backdrop함수 내에서 props.Confirm을 사용했기 떄문 ~
return (
<React.Fragment>
{ReactDom.createPortal(<Backdrop onConfirm={props.onConfirm}/>,document.getElementById('backdrop-root'))}
{ReactDom.createPortal(<ModalOverlay tilte={props.title} message={props.message} onConfirm={props.onConfirm}/>, document.getElementById('overlay-root'))}
</React.Fragment>
);
};
const Backdrop = props => {
return <div className={classes.backdrop} onClick={props.onConfirm} />
};
const ModalOverlay = props => {
return <Card className={classes.modal}>
<header className={classes.header}>
<h2>{props.title}</h2>
</header>
<div className={classes.content}>
<p>{props.message}</p>
</div>
<footer className={classes.actions}>
<Button onClick={props.onConfirm}>Okay</Button>
</footer>
</Card>
};
다른 컴포넌트에서도 사용되는 컴포넌트라면 외부 js파일로 구분해 컴포넌트를 만들어도 되지만,
하나의 컴포넌트 안에서만 사용된다면 하나의 js파일에서 처리해줘도 괜찮음.
* ref(참조)
다른 DOM요소에 접근해서 그것들로 작업을 할 수 있게 해준다.
예를들어 form을 입력할 때만 필요한데도, 키를 입력할때마다 state를 업데이트하는 것은 비효율적임.
이러한 경우에도 ref를 사용할 수 있다. (이 외에도 다른 기능이 있음)
+) ref도 useState처럼 리액트 훅
ref를 사용하면 state대신 사용자가 입력한 값을 불러올 수 있다.
//모든 리액트 훅과 마찬가지로 함수형 컴포넌트 내부에서만 사용 가능하다.
//초기화하려는 기본값이 필요하지만 여기서 중요하진 않음.
//여기서 중요한건 useRef();가 무엇을 반환하는가.
//왜냐하면 나중에 해당 ref와 작업할 수 있게 해주는 값을 반환해주기 때문임 ~
//즉 요소와 연결하여 해당 요소와 작업할 수 있게 해준다.
//초기값은 undefined. 기본값임. 쓸모는 없음.
//이제 리액트에 ref와 연결하고싶다고 알려줘야함.
//ref와 연결하려는 해당 요소에 가서 ref prop을 연결해주면 된다.
const nameInputRef = useRef();
//nameInputRef안에 있는 요소는 실제 DOM요소가 될 것.
//nameInputRef를 통해 출력되는 값은 항상 객체!
//그리고 항상 current 프롭을 가지고 있다.
//current prop은 그 ref가 연결된 실제 값을 가진다.
const ageInputRef = useRef();
결국 state의 값을 사용하는 모든 함수나 변수가 불필요해짐.
const enteredName = nameInputRef.current.value;
const entereUserdAge = ageInputRef.current.value;
ref와 input이 연결되면서 current.value로 사용자 입력값을 직접 받아 올 수 있게 됨.
if (enteredName.trim().length === 0 || entereUserdAge.trim().length === 0) {
setError({
title: 'Invalid input',
message: 'Please enter a valid name and age (non-empty values).',
});
return;
}
if (+entereUserdAge < 1) {
setError({
title: 'Invalid age',
message: 'Please enter a valid age (> 0).',
});
return;
}
props.onAddUser(enteredName, entereUserdAge);
};
그러면 아래쪽 조건에서 위에서 설정한 state에서 받아오는 변수가 아니라 ref 변수로 바꿔주면 된다.
state를 인식할 필요가 없으니 value(값 속성) 와 onChange(input에 대한 Change요소)는 필요 없어짐.
왜냐하면 변화를 감지할 필요가 없기 때문.
대신 ref가 필요한 input요소에 ref와 ref변수를 추가해주면된다.
이 방법을 사용하면 리액트 없이도 DOM을 조작할 수 있다.
일반적으로는 그러면 안되지만, 사용자가 입력한 값을 재설정하려는 경우에는 해도 괜찮다.
DOM을 조작하기 위해 ref를 사용하는 것이 매우 드물다.
CSS를 변경하거나 새로운 요소를 추가하는 것이 아닌, 사용자가 입력한 내용을 바꾸는 것일 뿐이라 괜춘
만약 이렇게 하기 싫으면 그냥 state사용해서 해도 괜찮다.
DOM요소와 상호작용하는 이 방법에는 "uncontrolled component" 제어되지 않는 컴포넌트라는 이름이 있다.
Uncontrolled Components – React
A JavaScript library for building user interfaces
reactjs.org
input에 들어가는 요소를 가져오긴 하지만, 다시 input에 데이터를 보내지는 않는다.
또한 내부 state에서 존재하기 때문에 리액트를 사용하지 않는다는 것.
'FE·Client > React' 카테고리의 다른 글
[React] useReducer() (0) | 2023.01.27 |
---|---|
[React] sideEffect() 와 useEffect() (0) | 2023.01.17 |
[React] 리액트 컴포넌트 스타일링, styled-components, 미디어쿼리, CSS 모듈 (0) | 2023.01.09 |
[React] 동적 배열 할당, 조건부 렌더링 (1) | 2023.01.06 |
[React] props.childern, State, 상향식 컴포넌트 통신(자식컴포넌트에서 부모컴포넌트로 데이터 넘기기), 상태 끌어올리기(Lifting State Up) (0) | 2023.01.04 |