5. ref:DOM에 이름 달기

히치키치·2021년 11월 15일
0

React_Basic

목록 보기
4/8
post-thumbnail

DOM 요소의 id

  1. public/index.html : id가 root인 div 요소
<body>
  <div id="root"></div>
</body>
  1. src/index.js : id가 root인 요소에 리액트 컴포넌트 랜더링
ReactDOM.render(<App/>,document.getElementById("root"))

리액트 컴포넌트 안에서 id 사용 가능 -> 권장 X
원칙적 : unique한 DOM의 id
문제 상황 발생 : 중복 id 가진 DOM 생성됨
ref 의 경우 : 전역적 작동 X, 컴포넌트 내부에서만 작동 X -> 문제 발생 ㅌ
불가피한 if 사용 필요한 경우 : 추가적 txt 붙여야 함

ref는 어떤 상황에 사용?

순수 js : DOM을 꼭 직접적으로 건들어야 하는 경우 사용
웹에서 input을 검증하기 위해 특정 id가진 input에 클래스 설정

<head>
(...)
  <script>
    function validate(){
      var input=document.getElementById("password");
      input.className="";
      if(input.value==="0000"){
          input.className="success";
      }
      else{
          input.className="failure";
      }

    }
  </script>
(...)
</head>
<body>
  <input type="password" id="password"/>
  <button onClick="validation()">Validation</button>
</body>

react : DOM에 접근하지 않고 리액트 컴포넌트의 state 이용

1. Validation 컴포넌트 생성

//input 검증 결과에 따른 화면 스타일
.success {
  /*입력한 값이 검증된 경우 (비번과 동일함)*/
  background-color: lightgreen;
}
.failure {
  /*입력한 값이 검증되지 않은 경우 (비번과 동일하지 않은 경우)*/
  background-color: lightcoral;
}

/
import React,{Component} from 'react';
import "./ValidationSample.css";

//1. Validation 컴포넌트 생성
class ValidationSample extends Component{
    //1-1. 초기 state 설정
    state={
        password:"", //비밀번호
        clicked:false, //버튼 클릭 X
        validated:false //비밀번호 검증 X
    }

    //2. 이벤트(input 입력) 발생시 실행되는 함수
    handleChange=(e)=>{
        this.setState( 
            //2-1. 입력 event의 값을 password의 값으로 설정
            {
                password:e.target.value
            }
        )
    }

    //3. 버튼 클릭시 실행되는 함수
    handleButtonClick=()=>{
        this.setState(
            {
                clicked:true, 
                //3-1. 버튼 클릭 여부 true로 설정
                validated:this.state.password==="0000" 
                //3-2. 입력한 비밀번호의 값이 0000인 경우 검증 상태 true됨

            }
        )
    }

    render(){
        return(
            <div>
                <input
                    type="password" 
                    //4-1. input에 입력되는 값은 password임
                    value={this.state.password} 
                    //4-2. input의 값은 state의 password 값임
                    onChange={this.handleChange} 
                    //4-3. input에 값이 입력되는 event 발생 시 실행 되는 함수
                    className={this.state.clicked?(this.state.validated?"success":"failure"):""}
                    //4-4. 입력된 값 검증 결과 : 참 & 유저가 click해 제출 -> success
                    //4-4. 입력된 값 검증 결과 : 거짓 & 유저가 click해 제출 -> failure
                    //4-4. 입력된 값 검증 결과 : 거짓 & 유저가 아직 click해 제출 안함 -> ""로 이전 상태 그대로임 
                    />
                <button onClick={this.handleButtonClick}>검증하기</button>
            </div>
        );
    }

}
export default ValidationSample;

2. App 컴포넌트에서 Validation 컴포넌트 렌더링


import './App.css';
import React,{Component} from 'react';
import ValidationSample from './ValidationSample';

class App extends Component{
  render(){
    {

      return (
        <ValidationSample/>
      );
    }
  }
}

export default App;

State로 해결 불가능해 ref 사용해 DOM에 직접적인 접근하는 경우
1. 특정 input에 포커스 주기
2. 스크롤 박스 조작
3. Canvas 요소에 그림 그리기

ref 사용

기본적 사용법

ref 속성 추가 : props 설정과 유사
콜백 함수의 파라미터 : ref
콜백 함수 배누에서 컴포넌트 멤버 변수에 ref 담는 코드

<input ref={(ref)=>{this.input=ref}} (....)/>

this.input=input 요소의 DOM

1. input에 ref 달기

    <input
        ref={(ref)=>this.input=ref}
        //this.input은 input 요소의 DOM을 가르킴
        type="password"
        value={this.state.password}
        onChange={this.handleChange} 
        className={this.state.clicked?(this.state.validated?"success":"failure"):""}
        />

2. 버튼 onClick 이벤트 코드 수정

    handleButtonClick=()=>{
        this.setState(
            {
                clicked:true, 
                validated:this.state.password==="0000" 
            }
        );
        this.input.focus();
        /*버튼 눌렀을 때 focus가 버튼으로 넘어가 
        input 텍스트 요소에 커서 보이지 X 인 걸 막음
        -> 버튼 눌렀을 때 focus가 다시 input 쪽으로 자동으로 넘어감*/
    }

component에 ref 달기

컴포넌트 내부에 있는 DOM을 컴포넌트 외부에 사용시 사용

기본적 사용법

<MyComponent ref={(ref)=>{this.myComponent=ref}}/>

스크롤 박스 있는 컴포넌트 생성, 부모 컴포넌트에서 스크롤 다운 작업 실행

1. 컴포넌트 초기 설정

1-1. 컴포넌트 파일 생성

import React,{Component} from 'react';

//1. ScrollBox 컴포넌트 생성
class ScrollBox extends Component{
    //2. JSX 인라인 스타일링 문법으로 스크롤 박스 생성
    render(){
        const style={
            border: "1px solid black",
            height: "300px",
            width :"300px",
            overflow:"auto",
            position:"relative"

        };

        const innerstyle={
            width : "100%",
            height : "650px",
            background:"linear-gradient(white, black)"
        }
        return (
            //3.최상위 DOM에 ref 달기
            <div style={style}
            ref={(ref)=>{this.box=ref}}>
                <div style={innerstyle}/>
            </div>
        )
    }
}
export default ScrollBox;

1-2. App 컴포넌트에 스크롤 박스 컴포넌트 렌더링


import './App.css';
import React,{Component} from 'react';
import ValidationSample from './ValidationSample';
import ScrollBox from './ScrollBox';

class App extends Component{
  render(){
    {

      return (
        <ScrollBox/>
      );
    }
  }
}
export default App;

2. 컴포넌트에 메서드 생성

DOM 노드가 가진 다음의 활용해 컴포넌트에 스크롤바를 맨 아래로 내리는 매서드 생성

  • scrollTop : 세로 스크롤바 위치 (0~350)
  • scrollHeight : 스크롤 박스 내부 높이 (650)
  • clientHeight : 스크롤 박스 외부 높이 (300)
    => 스크롤바 맨 아래 = scrollHeight - clientHeight
import React,{Component} from 'react';


class ScrollBox extends Component{

    //스크롤바 가장 밑으로 내리는 메서드 작성
    scrollToBottom=()=>{
        const {scrollHeight, clientHeight}=this.box;
        //비구조화 할당 문법
        this.box.scrollTop=scrollHeight-clientHeight;
    }
    
    render(){
        const style={
            border: "1px solid black",
            height: "300px",
            width :"300px",
            overflow:"auto",
            position:"relative"

        };

        const innerstyle={
            width : "100%",
            height : "650px",
            background:"linear-gradient(white, black)"
        }


        return (
            
            <div style={style}
            ref={(ref)=>{this.box=ref}}>
                <div style={innerstyle}/>
            </div>
        )
    }
}



export default ScrollBox;

3. 컴포넌트에 ref 달고 내부 메서드 사용

import './App.css';
import React,{Component} from 'react';
import ValidationSample from './ValidationSample';
import ScrollBox from './ScrollBox';

class App extends Component{
  render(){
    {

      return (
        <div>
          <ScrollBox ref={(ref)=>this.scrollBox=ref}/>
          <button onClick={()=>this.scrollBox.scrollToBottom()}> 맨밑으로</button>
        </div>
      );
    }
  }
}

export default App;
  • onClick={this.scrollBox.scrollBottom} 으로 작성하는 경우 컴포넌트 첫 렌더링 때 this.scrollBoxundefined임.
  • onClick 에서 화살표 함수 문법 이용해 새로운 함수 만들고 그 함수 내부에서 scrollBox.scrollToBottm 실행 시 오류 없음
    -> 버튼을 눌렀을 때 이미 렌더링 했기 때문

ES6의 비구조화 할당 문법

객체에서 특정 값 추출해 따로 레퍼런스 만들 때 유용

//예제1.
const obj={
  foo:1,
  bar:2
};
const {foo,bar}=obj;
console.log(foo,bar);
//예제2.
const obj={
	foo:1,
    	bar:2
}

function print({a,b}){
  console.log(a,b);
}
print(obj);

리액트 컴포넌트에서 state나 props 참조시 자주 사용

render(){
	const {name,num}=this.props;
  return(
  <div>
    <div>{name}</div>
    <div>{num}</div>
  </div>
  )
}

0개의 댓글