Skip to content

Commit 4554341

Browse files
committed
ref and dom 폴더
1 parent 4f9330e commit 4554341

File tree

6 files changed

+185
-0
lines changed

6 files changed

+185
-0
lines changed

ref-and-dom/Seogeurim/.gitkeep

Whitespace-only changes.

ref-and-dom/chaeeun037/.gitkeep

Whitespace-only changes.

ref-and-dom/jiyong1/.gitkeep

Whitespace-only changes.

ref-and-dom/jonghopark95/.gitkeep

Whitespace-only changes.

ref-and-dom/peanut-lover/.gitkeep

Whitespace-only changes.

ref-and-dom/peanut-lover/README.md

+185
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
# Ref 와 DOM
2+
3+
Ref는 render 메서드에서 생성된 DOM 노드나 React 엘리먼트에 직접 접근하는 방법을 제공합니다.
4+
5+
일반적인 React의 데이터 플로우에서 `props`는 부모 컴포넌트가 자식과 상호작용 할 수 있는 유일한 수단입니다. 자식을 수정하려면 **새로운 props**를 전달하여 자식을 다시 렌더링 해야합니다.
6+
7+
그러나, 일반적인 데이터 플로우에서 벗어나 직접적으로 자식을 수정해야 하는 경우도 가끔씩 있습니다. 수정할 자식은 **React 컴포넌트의 인스턴스** 일 수 도 있고 **DOM 앨리먼트** 일 수도 있습니다.
8+
9+
Ref의 바람직한 사용 사례는 다음과 같습니다.
10+
11+
- 포커스, 텍스트 선택 영역, 혹은 미디어의 재생을 관리할 때.
12+
13+
- 애니메이션을 직접적으로 실행 시킬때 => **구체인 예시 정리하기**
14+
15+
- **서드 파티 DOM 라이브러리**를 React 와 같이 사용할 때
16+
17+
- 개인적으로 D3js와 함께 쓰는 방법을 익히고 싶습니다.
18+
19+
## Ref 생성하기
20+
21+
Ref는 `React.createRef()`를 통해 생성되고 `ref`어트리뷰트를 통해 React Element에 부착됩니다. 보통 컴포넌트의 인스턴스가 생성될 때 Ref를 프로퍼티로서 추가하고, 그럼으로서 **컴포넌트의 인스턴스의 어느 곳에서도 Ref에 접근할 수 있게 합니다.**
22+
23+
```jsx
24+
class MyComponent extends React.Component {
25+
constructor(props) {
26+
super(props);
27+
this.myRef = React.createRef();
28+
}
29+
render() {
30+
return <div ref={this.myRef}></div>;
31+
}
32+
}
33+
```
34+
35+
## Ref에 접근하기
36+
37+
`render` 메서드 안에서 ref가 엘리먼트에게 전달되었을 때, 그 노드를 향한 참조는 ref의 `current`어트리뷰터에 담기게 됩니다.
38+
39+
```js
40+
const node = this.myRef.current;
41+
```
42+
43+
ref의 값은 노드 유형에 따라 다릅니다.
44+
45+
- `ref`어트리뷰트가 **HTML 엘리멘트**에 쓰였다면, 생성자에서 `React.createRef()`로 생성된 `ref`는 자신을 전달받은 **DOM 엘리먼트**`current`프로퍼티의 값으로서 받습니다.
46+
47+
- `ref` 어트리뷰트가 **커스텀 클래스 컴포넌트**에 쓰였다면, `ref`객체에 마운트된 컴포넌트의 인스턴스를 `current`프로퍼티의 값으로서 받습니다.
48+
- **함수 컴포넌트는 인스턴스가 없기 때문에 함수 컴포넌트에 ref 어트리뷰트를 사용할 수 없습니다**.
49+
50+
커스텀 컴포넌트에서 ref를 써서도 안되고 거의 쓸일도 없습니다. 대부분 DOM 엘리먼트에 직접 접근할 이유가 있을 때 사용하게 됩니다.
51+
52+
```jsx
53+
class CustomTextInput extends React.Component {}
54+
const CustomTextInput = () => {
55+
const textInput = useRef();
56+
57+
const focusTextInput = () => {
58+
textInput.current.focus();
59+
};
60+
return (
61+
<div>
62+
<input type="text" ref={this.textInput} />
63+
<input
64+
type="button"
65+
value="Focus the text input"
66+
onClick={focusTextInput}
67+
/>
68+
</div>
69+
);
70+
};
71+
```
72+
73+
컴포넌트가 마운트 될 때 React는 `current` 프로퍼티에 DOM 엘리먼트를 대입하고, 컴포넌트의 마운트가 해제될 때 `current` 프로퍼티를 다시 null 로 돌려놓습니다.
74+
75+
> 이 부분이 중요합니다. 마운트가 해제될 때 current를 null로 처리해줌으로써 DOM 인스턴스도 GC에 의해 정리되게 될 것입니다.
76+
77+
`ref`를 수정하는 작업은 `componentDidMount`또는 `componentDidUpdate`와 같은 생명주기 메서드가 호출 되기전에 이뤄집니다.
78+
79+
## 콜백 ref
80+
81+
React는 ref가 설정되고 해제되는 상황을 세세하게 다룰 수 있는 "콜백 ref"이라 불리는 ref를 설정하기 위한 또 다른 방법을 제공합니다.
82+
83+
#### DOM element에 ref 어트리뷰트에 함수를 넘길 수 있는 것 아시나요?
84+
85+
ref값이 아닌 함수를 전달 할 수 있습니다. 전달된 함수는 다른 곳에 저장되고 접근될 수 있는 React 컴포넌트의 인스턴스나 DOM 엘리먼트를 인자로서 받습니다.
86+
87+
즉, 마운트 시점에 해당 콜백 ref가 실행 되는 것이죠.
88+
89+
```jsx
90+
let textInput = null;
91+
const CustomTextInput = () => {
92+
const setTextInputRef = (element) => {
93+
textInput = element;
94+
};
95+
const focusTextInput = () => {
96+
if (textInput) textInput.focus();
97+
};
98+
useEffect(() => {
99+
focusTextInput();
100+
return () => {
101+
// clear
102+
};
103+
}, []);
104+
return (
105+
<div>
106+
<input type="text" ref={this.setTextInputRef} />
107+
<input
108+
type="button"
109+
value="Focus the text input"
110+
onClick={focusTextInput}
111+
/>
112+
</div>
113+
);
114+
};
115+
```
116+
117+
위 예제에서는 인스턴스가 마운트 될 때 `input` DOM 엘리먼트를 인자로 `ref`콜백을 호출합니다. 그리고 컴포넌트의 인스터스의 마운트가 해제될 때, `ref`콜백을 null과 함께 호출합니다.
118+
119+
- 콜백 ref에 관한 주의 사항
120+
121+
`ref`콜백이 **인라인 함수로 선언**되었다면 `ref`콜백은 업데이트 과정 중에 처음에는 `null`로, 그 다음에는 DOM 엘리먼트로, 총 두 번 호출됩니다. 이러한 현상은 매 렌더링마다 `ref`콜백의 새 인스턴스가 생성되므로 React가 이전에 사용된 ref를 제거하고 새 ref를 설정해야하기 때문에 일어납니다.
122+
123+
# Ref 사용 예시
124+
125+
### Input Element 제어
126+
127+
가장 흔히 쓰이는 방식입니다. DOM의 focus 함수를 호출하고 싶거나 disabled 시키고 싶을 때 사용할 수 있습니다.
128+
129+
```jsx
130+
import React, { useRef } from "react";
131+
132+
function Field() {
133+
const inputRef = useRef(null);
134+
135+
function handleFocus() {
136+
inputRef.current.disabled = false;
137+
inputRef.current.focus();
138+
}
139+
140+
return (
141+
<>
142+
<input disabled type="text" ref={inputRef} />
143+
<button onClick={handleFocus}>활성화</button>
144+
</>
145+
);
146+
}
147+
```
148+
149+
### audio Element 제어
150+
151+
또 다른 사례로 audio 엘리먼트 제어를 들 수 있습니다.
152+
153+
음악 파일의 재생하거나 중지할 수 있는 컴포넌트를 작성하면 아래와 같습니다.
154+
155+
```jsx
156+
import React, { useRef } from "react";
157+
import music from "./music.mp3";
158+
159+
function Player() {
160+
const audioRef = useRef(null);
161+
const handlePlay = () => {
162+
audioRef.current.play();
163+
};
164+
const handlePause = () => {
165+
audioRef.current.pause();
166+
};
167+
return (
168+
<>
169+
<figure>
170+
<figcaption>Eyes on You (Sting) - Network 415:</figcaption>
171+
<audio src={music} ref={audioRef}>
172+
Your browser does not support the
173+
<code>audio</code> element.
174+
</audio>
175+
</figure>
176+
<button onClick={handlePlay}>재생</button>
177+
<button onClick={handlePause}>중지</button>
178+
</>
179+
);
180+
}
181+
```
182+
183+
버튼으로 audio 를 제어할 수 있습니다.
184+
185+
https://codesandbox.io/s/react-refs-45hwd?from-embed

0 commit comments

Comments
 (0)