2021.07.16 React ref_정리노트
오늘은 5장 정리!
http://www.yes24.com/Product/Goods/62597469
ref
refrence 줄임말. html 에서 id 선택자를 이용해 특정 id 를 가진 요소에 DOM 작업을 하는 것처럼 리액트에서도 ref 작업이 가능하다.
DOM 이 먼지 모른다면 이렇게 또 글 홍보 ㅎ
https://korinkorin.tistory.com/38
public/index.html
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
내가 리액트 흐름할 때도 보았던 index.html 에서도 보면, 여기서도 id가 root 인 요소에서 컴포넌트를 렌더링하라는 코드가 있다.
하지만 id는 고유의 값이므로, 여러 컴포넌트에서 겹칠 위험이 있으므로 특수한 경우가 아니라면 사용을 지양함.
다른 라이브러리나 프레임워크와 함께 id 를 사용해야하는 상황이 발생한다면, 컴포넌트를 만들 때마다 id 뒤에 추가 텍스트를 붙여서 ( button01, button02 ... ) 중복 id 사용을 방지해야한다.
그러면 ref를 어떤 상황에서 사용해야할까?
바로 DOM 을 직접적으로 건드릴 때 !
순수 자바스크립트를 사용하는 해당 코드를 보면, 비밀번호가 0000일 때, 초록색깔 인풋 클래스가 적용되고, 그렇지 않은경우는 빨간색의 인풋 클래스를 띄워준다.
하지만 리액트에서는 DOM 에 접근하지 않고, state 로 해당 작업을 해줄 수 있기 때문에 오늘은 클래스형 컴포넌트로 위와 같은 기능을 하는 코드를 리액트로 같이 정리해보겠움! 함수형은 Hooks 에서 ref 작업을 해야하기 때문에 다음에 책과 같이 나왔을 때 다뤄보겠음 ㅎㅅㅎ
src/ValidationSample.css (새로 생성)
src/ValidationSample.js (새로 생성)
src 에 css ,js 파일을 작성해주고 아까 예제 파일처럼 기능을 js 파일에다가 작성해봅씨단
src/ValidationSample.js
코드랑 주석이랑 합쳐져서 헷갈리니까 복사해서 각자 IDE 에서 보기!
import React, { Component } from "react";
// css import
import "./ValidationSample.css";
class ValidationSample extends Component {
state = {
password: "",
clicked: false,
validated: false,
};
// password 값을 현재 input 의 value 로 state 업데이트
handleChange = (e) => {
this.setState({
password: e.target.value,
});
};
handleButtonClick = () => {
this.setState({
clicked: true,
// handleChange 로 받아온 value 가 0000 과 같으면 true, 아니면 false 반환
validated: this.state.password === "0000",
});
// 클릭 이벤트가 발생하면, input 이 focus 가 됨.
this.korin.focus();
};
render() {
return (
<div>
<input
// ref 추가
ref={(ref) => {
this.korin = ref;
}}
type="password"
value={this.state.password}
// onChage event 발생시 handleChange 함수 호출
onChange={this.handleChange}
className={
// 처음에는 빈 문자열 className 이지만, clicked = true 면 validated 를 판별하는 안의 식으로 들어감.
this.state.clicked
? // validate 가 true 면 success, false 면 failure 로 className 을 바뀌줌.
this.state.validated
? "success"
: "failure"
: // clicked = false 시 className 은 빈 문자열 전달.
""
}
/>
{/* onClick 이벤트로 handleButtonClick 함수 호출 */}
<button onClick={this.handleButtonClick}>유효성 검증하기</button>
</div>
);
}
}
export default ValidationSample;
먼저 input 의 값이 바뀌면 즉, onChange 이벤트가 발생하면, password의 state 값을 업데이트하고, 버튼을 클릭하면 현재 인풋의 value 를 가져오는 handleButtoClick 함수를 호출한다. handleButtoClick 함수는 다시 clicked,validated 의 state 값을 업데이트 한 뒤!!!!!
input 의 className 을 이중 조건부 삼항연산자를 통해 바꿔준다.
후 꽤 헷갈렸담.. 쨋든 App 에다가 적어주고 실행해봅씨다.
src/App.js
실행화면
class 이름이 빈 값이었다가,
input 에 0000을 입력하고 버튼을 누르면, success 의 클래스가 생기고, 해당 클래스의 css 가 먹히고,
다른 것을 채우면, failure 라는 클래스가 생기면서, 해당 css 가 먹힌다!
이렇게 state 로 구현해보았지만, 가끔 state로 해결할 수 없는 기능은
특정 input 에 포커스 주기
스크롤 박스 조작하기
Canvas 요소에 그림 그리기
등등.. 이럴 때는 어쩔 수 없이 DOM 에 직접적으로 접근해야한다. 이 때 ref 를 사용하니 자 이제 진짜 ref 정리 ㄱ!
ref 사용 방법은 두 가지이니까 같이 정리 ㄱ!
콜백함수 사용
ref 를 만드는 가장 기본적인 방법은 콜백 함수를 사용하는 것이다. ref 를 달고자 하는 요소에 ref 라는 콜백 함수를 props 로 전달해주면 된다. 이 콜백 함수는 ref 값을 파라미터로 전달받는다. 그리고 함수 내부에서 파라미터로 받은 ref를 컴포넌트의 멤버 변수로 설정해준다.
<input ref={(ref)=>{this.input=ref}} />
// (ref) : 함수의 파라미터로 ref 를 받음
// 멤버 변수 this.input 을 ref 로 설정
여기서 this.input 은 DOM 에서의 input 요소를 가리키고, ref의 이름은 아무거나 써도 됨. this.input 말고 this.korin=ref 로 해도 된단 말씀!
음음.. 근데 나는 아직 콜백함수라는 것이 정확히 이해가 안되어서 오늘도 역시
https://www.youtube.com/watch?v=s1vpVCrT8f4
갓...엘리님의 영상을 참고했다.
자바스크립트는 기본적으로 호이스팅된 결과를 동기적으로 수행하는데, 예측이 불가한 것들의 비동기적 처리를 할 때 callback 함수가 유용하게 쓰인다.
콜백 함수는 어떤 이벤트가 발생했거나, 특정 시점에 도달했을 때 호출되는 함수로, 일반적으로 다른 함수에 넘기거나, 객체의 프로퍼티로 사용한다.
영상과 다른 블로거분들의 글들을 읽어봐도 한번에 와닿지는 않는다.. 엘리님 말처럼 콜백지옥이 생성되면 너무나도 가독성이 떨어지기 때문에.. 흑흑 역시 쳐보면서 나는 익히는게 최고인 거 같음..
우리가 위에서 정리했던 코드도 이벤트가 발생할때, 즉 특정 시점에서 함수를 호출하니까 콜백함수를 사용해서 같이 쳐봅시다!
지금 우리가 버튼을 클릭하면,
깜빡깜빡 거리는 텍스트 커서가 인풋창에서 사라진다.
이 커서! 이 커서는 focus 가 될 때 생기므로, 버튼을 클릭했을 때, 포커스가 되도록 설정해보자!
이렇게 우리가 적어놓은 코드에 ref 를 추가한다. 이제 this.input 은 input 요소의 DOM 을 가리킨다.
클릭했을 때, input 이 focus 가 된다!
클릭했을 때, 커서가 생기면 성공!
아까 이름 바꿔도 된다했으니까, 만약에
this.korin = ref 로 설정했다면, 위에서도 똑같이 통일만 해주면 잘 작동한다!
createRef 사용
리액트 내장 함수로, v16.3 부터 사용되며, 이전 버전에는 작동하지 않는다.
createRef() 를 멤버 변수에 담아주고, 해당 멤버 변수를 ref 를 달고자 하는 요소에 ref props 로 넣어주기!
DOM 에 접근하려면 뒤에 .current 를 붙여서 접근하면 된다!
이제 컴포넌트 자체에 ref 를 달아보자!
리액트에서는 컴포넌트에도 ref 를 달 수 있는데, 이 방법은 주로 컴포넌트 내부에 있는 DOM 을 컴포넌트 외부에서 사용할 때 쓴다.
< MyComponent
ref={(ref)=>{this.myComponent=ref}} />
이렇게 DOM 에 ref 를 다는 방법과 똑같다!
이렇게 하면 컴포넌트 ( 여기서는 MyComponent ) 내부의 메서드 및 멤버 변수에도 접근할 수 있다. 즉, 컴포넌트 내부의 ref 에도 접근할 수 있음. ( 예시로, myComponet.handleClick, myComponet.input 등등 )
음음 역시 쳐보면서 정리 ㄱ! 스크롤 박스가 있는 컴포넌트를 하나 만들고, 스크롤바를 맨 위로 올리는 작업을 부모 컴포넌트에서 실행해봅씨다
src/ScrollBox.js ( 새로 생성 )
import React, { Component } from "react";
class ScrollBox extends Component {
render() {
// 인라인 스타일링 문법
const style = {
border: "1px solid black",
height: "300px",
width: "300ox",
// 넘치면 스크롤 생기는 css 속성
overflow: "auto",
position: "relative",
};
const inlineStyle = {
width: "100%",
height: "650px",
background: "linear-gradient(white,black)",
};
return (
<>
{/* 최상위 DOM 에 ref 달기 */}
<div
style={style}
ref={(ref) => {
this.box = ref;
}}
>
<div style={inlineStyle}></div>
</div>
</>
);
}
}
export default ScrollBox;
만들어줬으면 App 에 렌더링!
src/App.js (클래스형으로 재생성)
이렇게 간단하게 ..?
스크롤이 있는 박스를 만들었다. 이제 부모컴포넌트에서 직접 메소드를 생성해주자!
자바스크립트 스크롤바를 내릴 때 DOM 노드를 사용하는데,
scrollTop
세로 스크롤바 위치
scrollHeight
스크롤이 있는 박스 안의 div 높이
clientHegiht
스크롤이 있는 박스의 높이
오... 무슨소린지 몰라서 또 찾아봄 ㅎ
아이고........ 어렵다...... ㅋㅋㅋ큐ㅠㅠㅠ 맨 밑으로 가고 싶으면 , scrollHeight 에서 clientHeight 를 빼고, 맨 위로 가고 싶으면 반대로 clientHeight에서 scrollHeight 를 빼자!
난 맨 위로 가고 싶어서 clientHeight에서 scrollHeight 를 뺄 예정!
우리가 부모컴포넌트에서는 자식 컴포넌트들의 메서드에 접근할 수 있다했으니, 먼저 ScrollBox 에다가 메소드를 적어주고 App 부모 컴포넌트에서 불러와봅시다!
src/ScrollBox
해당 메소드 부분을 추가해주자.
this.box 는 우리가 추가해준 ref. 즉 , 최상위 DOM 을 가리킴!
역시 비구조화 할당을 통해서 간단히 표현해주고, 이제 만들어줬으면 App 으로 가서 불러와봅씨단.
src/App
여기서 이상한건 분명 우리가 메소드에 접근할 때 onClick={this.scrollBox.scrollToTop} 이렇게 적으면 접근된다했는데,,?
문법상을로 오류는 아님. 하지만 처음 컴포넌트가 렌더링 될 때는 this.scrollBox 가 값이 undefined 이므로, this.scrollBox.scrollToTop 값을 읽어 오는 과정에서 오류가 발생한다.
그렇기 때문에 아예 화살표 함수를 만들고, 그 내부에서 this.scrollBox.scrollToTop 메서드를 실행하면, 버튼을 누를 때 ( 이미 렌더링을 한 번 해서 this.scrollBox 를 설정한 시점 ) 해당 메서드를 실행하기 때문에 오류를 발생시키지 않는다..!
이렇게 부르게 되면 값이 undefiend이기 때문에 오류가 뜸..!
후... 이제 실행해봅시다!!!!!!!
이렇게 맨 끝까지 내리고
top 버튼을 누르면 맨 위로 감....!
ref 는 컴포넌트 내에서 직접 DOM 에 접근하는 것이기 때문에, 사용하기전 꼭 사용하지 않고 구현할 수 있는 방법을 먼저 찾아보고 ref 를 사용하자...! 그리고 서로 다른 컴포넌트끼리 ref 는 리액트 설계상 어긋나기 때문에 금물!!!!!!! 컴포넌트 끼리 데이터를 교류할 때는 꼭 부모-자식 의 흐름으로 교류하자..!
와......장수 적다고 쉽게 봤었는데 저어어어얼대 아님...^^ 사실 완전히 이해는 안된 것 같다.. 클래스 메서드 관련된 개념도 많이 나오고, 뭔가 쓰는 개념이랑 접근하는 방법이 너무 생소해서..진짜 함수형 아직 시작도 안했는데 어려운 개념인 것 같다 ㅠ ... 흑... 마찬가지로 여기는 내 정리노트기 때문에 기술이 는다면 역시나..또 와서 수정해야징... 오늘은 지쳐서 포스팅 빨리 끝끄그ㅡ그끄ㅡ끝ㅌ!!!!!!!
'React' 카테고리의 다른 글
2021.07.19 React Life Cycle (2) | 2021.07.21 |
---|---|
2021.07.19 React Component 반복 (1) | 2021.07.19 |
07.13 React event handling (0) | 2021.07.14 |
2021.07.11 React props,state (4) | 2021.07.12 |
2021.07.06 React ? (0) | 2021.07.06 |
댓글