๋ณธ๋ฌธ์œผ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ

[๋ฆฌ์•กํŠธ๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ธฐ์ˆ ] 5์žฅ - ref: DOM์— ์ด๋ฆ„ ๋‹ฌ๊ธฐ

2020-04-02-๋ฆฌ์•กํŠธ๋ฅผ-๋‹ค๋ฃจ๋Š”-๊ธฐ์ˆ -5์žฅ-ref-dom์—-์ด๋ฆ„-๋‹ฌ๊ธฐ-image-0

์ด ๊ธ€์€ ๊น€๋ฏผ์ค€(velopert)๋‹˜์˜ ๋ฆฌ์•กํŠธ๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ธฐ์ˆ ์„์ฐธ์กฐํ•˜์—ฌ ์ž‘์„ฑํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.


์ผ๋ฐ˜ HTML์—์„œ DOM ์š”์†Œ์— ์ด๋ฆ„์„ ๋‹ฌ ๋•Œ id๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

<div id="my-element"></div>

์ด๋ ‡๊ฒŒ ์š”์†Œ์— id๋ฅผ ๋‹ฌ๋ฉด CSS์—์„œ ํŠน์ • id์— ํŠน์ • ์Šคํƒ€์ผ์„ ์ ์šฉํ•˜๊ฑฐ๋‚˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ํ•ด๋‹น id๋ฅผ ๊ฐ€์ง„ ์š”์†Œ๋ฅผ ์ฐพ์•„ ์ž‘์—…ํ•  ์ˆ˜ ์žˆ๋‹ค.

HTML์—์„œ id๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, ๋ฆฌ์•กํŠธ ๋‚ด๋ถ€์—์„œ DOM์— ์ด๋ฆ„์„ ๋‹ค๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋Š”๋ฐ๊ทธ๊ฒƒ์ด ref(reference)์˜ ๊ฐœ๋…์ด๋‹ค.

๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ๋„ id๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, HTML์—์„œ DOM์˜ id๋Š” ์œ ์ผํ•ด์•ผํ•˜๋Š”๋ฐ, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ์‚ฌ์šฉ๋˜๋ฉด ์ค‘๋ณต id๊ฐ€ ์ƒ๊ธฐ๋‹ˆ ์ž˜๋ชป๋œ ์‚ฌ์šฉ์ด๋‹ค. ref๋Š” ์ „์—ญ์ ์œผ๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š๊ณ , ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ๋งŒ ์ž‘๋™ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.


ref๋Š” ์–ด๋–ค ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ?#

ref๋Š” "ํŠน์ • DOM์„ ๊ผญ ์ง์ ‘์ ์œผ๋กœ ๊ฑด๋“œ๋ ค์•ผ ํ•  ๋•Œ" ์‚ฌ์šฉํ•œ๋‹ค. ์ˆœ์ˆ˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธํ˜น์€ jQuery๋กœ ๋งŒ๋“  ์›น์‚ฌ์ดํŠธ์—์„œ input ์„ ๊ฒ€์ฆํ•  ๋•Œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•œ๋‹ค.

<!DOCTYPE html><html><head>  <meta charset="utf-8">  <meta name="viewport" content="width=device-width">  <title>Example</title>  <style>    .success {      background-color: lightgreen;    }    .failure {      background-color: lightcoral;    }  </style>  <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"></input>  <button onclick="validate()">Validate</button></body></html>

2020-04-02-๋ฆฌ์•กํŠธ๋ฅผ-๋‹ค๋ฃจ๋Š”-๊ธฐ์ˆ -5์žฅ-ref-dom์—-์ด๋ฆ„-๋‹ฌ๊ธฐ-image-1


๋ฆฌ์•กํŠธ์—์„œ๋Š” ์ด๋Ÿฐ ์ž‘์—…์ด ๊ตณ์ด DOM์— ์ ‘๊ทผํ•˜์ง€ ์•Š์•„๋„ state ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. src ๋””๋ ‰ํ† ๋ฆฌ์— ValidationSample.css ์™€ ValidationSample.js ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž.

ValidationSample.css

.success {    background-color: lightgreen;}
.failure {    background-color: lightcoral;}

ValidationSample.js

import React, {Component} from 'react';import './ValidationSample.css';
class ValidationSample extends Component {    state = {        password: '',        clicked: false,        validated: false,    };
    handleChange = (e) => {        this.setState({            password: e.target.value,        });    };
    handleButtonClick = () => {        this.setState({            clicked: true,            validated: this.state.password === '0000',        });    };
    render() {        return (            <div>                <input                    type="password"                    value={this.state.password}                    onChange={this.handleChange}                    className={                        this.state.clicked                            ? this.state.validated                                ? 'success'                                : 'failure'                            : ''                    }                />                <button onClick={this.handleButtonClick}>Validate</button>            </div>        );    }}
export default ValidationSample;

ValidationSampe.js ๋ฅผ ๋ณด๋ฉด, input์˜ onChange ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ, handleChange ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ password ๊ฐ’์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ , button ์—์„œ onClick ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ handleButtonClick ์„ ํ˜ธ์ถœํ•˜์—ฌ clicked ๊ฐ’์„ ์ฐธ์œผ๋กœ ์„ค์ •ํ•˜๊ณ , validated ๊ฐ’์„ ๊ฒ€์ฆ ๊ฒฐ๊ณผ๋กœ ์„ค์ •ํ–ˆ๋‹ค.

input ์˜ className ์€ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๊ธฐ ์ „์—๋Š” ๋นˆ ๋ฌธ์ž์—ด, ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅธ ํ›„์— ๊ฒ€์ฆ์ด์„ฑ๊ณตํ•˜๋ฉด success , ์‹คํŒจํ•˜๋ฉด failure ๋กœ ์„ค์ •ํ–ˆ๋‹ค. ์ด์— ๋”ฐ๋ผ input ์˜ ์ƒ‰์ƒ์ด์ดˆ๋ก์ƒ‰ ๋˜๋Š” ๋นจ๊ฐ„์ƒ‰์œผ๋กœ ๋‚˜ํƒ€๋‚œ๋‹ค.

App ์ปดํฌ๋„ŒํŠธ์—์„œ ValidationSample ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถˆ๋Ÿฌ์™€ ๋ Œ๋”๋งํ•ด๋ณธ๋‹ค.

App.js

import React, {Component} from 'react';import ValidationSample from './ValidationSample';
class App extends Component {    render() {        return <ValidationSample />;    }}
export default App;

2020-04-02-๋ฆฌ์•กํŠธ๋ฅผ-๋‹ค๋ฃจ๋Š”-๊ธฐ์ˆ -5์žฅ-ref-dom์—-์ด๋ฆ„-๋‹ฌ๊ธฐ-image-2

์›ํ•˜๋Š” ๊ฒฐ๊ณผ๊ฐ€ ์ž˜ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ๋Š” DOM์—์ ‘๊ทผํ•ด์•ผ ํ–ˆ๋˜ ๊ธฐ๋Šฅ์„ ๋ฆฌ์•กํŠธ์—์„œ๋Š” state๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ state ๋งŒ์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†๋Š” ๊ธฐ๋Šฅ๋“ค์ด ์žˆ๋‹ค.

(์˜ˆ์‹œ)

  • ํŠน์ • input์— ํฌ์ปค์Šค ์ฃผ๊ธฐ

  • ์Šคํฌ๋กค ๋ฐ•์Šค ์กฐ์ž‘ํ•˜๊ธฐ

  • Canvas ์š”์†Œ์— ๊ทธ๋ฆผ ๊ทธ๋ฆฌ๊ธฐ

์ด๋ ‡๊ฒŒ DOM์— ์ง์ ‘ ์ ‘๊ทผํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์„ ์œ„ํ•ด ref๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.


ref ์‚ฌ์šฉ#

ref๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‘ ๊ฐ€์ง€์ด๋‹ค.

์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ํ†ตํ•œ ref ์„ค์ •#

ref๋ฅผ ๋งŒ๋“œ๋Š” ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ•์€ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ref๋ฅผ ๋‹ฌ๊ณ ์ž ํ•˜๋Š”์š”์†Œ์— ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ref๋ฅผ props๋กœ ์ „๋‹ฌํ•ด์ฃผ๋ฉด ๋œ๋‹ค. ์ด ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” ref ๊ฐ’์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๊ณ , ref๋ฅผ ์ปดํฌ๋„ŒํŠธ์˜ ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋กœ ์„ค์ •ํ•ด์ค€๋‹ค.

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

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด this.input ์ด input ์š”์†Œ์˜ DOM์„ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ๋œ๋‹ค. ์ด ๋•Œ, ์ด๋ฆ„์€ this.input ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์›ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์ž์œ ๋กญ๊ฒŒ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

createRef๋ฅผ ํ†ตํ•œ ref ์„ค์ •#

๋ฆฌ์•กํŠธ์— ๋‚ด์žฅ๋˜์–ด ์žˆ๋Š” createRef ๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ref๋ฅผ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์€ ๋ฆฌ์•กํŠธ v16.3๋ถ€ํ„ฐ ๋„์ž…๋˜์—ˆ๋‹ค.

import React, {Component} from 'react';
class RefSample extends Component {    input = React.createRef();
    handleFocus = () => {        this.input.current.focus();    };
    render() {        return (            <div>                <input ref={this.input} />            </div>        );    }}
export default RefSample;

createRef๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ref๋ฅผ ๋งŒ๋“ค๋ ค๋ฉด ๋จผ์ € ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋กœ React.createRef() ๋ฅผ ๋‹ด์•„์ค€๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋ฅผ ref๋ฅผ ๋‹ฌ๊ณ ์ž ํ•˜๋Š” ์š”์†Œ์— ref props๋กœ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.

์ด๋ ‡๊ฒŒ ์„ค์ •ํ•˜๊ณ  ๋‚˜์ค‘์— DOM์— ์ ‘๊ทผํ•˜๋ ค๋ฉด this.input.current ์ฒ˜๋Ÿผ ๋’ค์— .current ๋ฅผ ๋„ฃ์–ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

ref๋กœ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ input์œผ๋กœ ํฌ์ปค์Šค ์ด๋™ ๊ตฌํ˜„#

์œ„์—์„œ ๋งŒ๋“ค์—ˆ๋˜ ValidationSample ์—์„œ Validate ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ input์œผ๋กœ ํฌ์ปค์Šค๊ฐ€๋„˜์–ด๊ฐ€๋„๋ก ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ด๋ณธ๋‹ค.

input์— ref ๋‹ฌ๊ธฐ#

๋ฐฐ์šด ๋Œ€๋กœ input ์š”์†Œ์— ref๋ฅผ ์ ์šฉํ•œ๋‹ค.

ValidationSample.js

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

๋ฒ„ํŠผ onClick ์ด๋ฒคํŠธ ์ˆ˜์ •#

๋ฒ„ํŠผ์—์„œ onClick ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ input์— ํฌ์ปค์Šค๋ฅผ ์ฃผ๋„๋ก ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•œ๋‹ค. ref ๋ฅผ ์ ์šฉํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด์ œ this.input ์œผ๋กœ DOM์„ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์ผ๋ฐ˜ DOM ์˜ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ValidationSample.js

handleButtonClick = () => {    this.setState({        clicked: true,        validated: this.state.password === '0000',    });    this.input.focus();};

์ด์ œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณด๋ฉด ๋ฒ„ํŠผ ํด๋ฆญ์‹œ ํฌ์ปค์Šค๊ฐ€ input ์š”์†Œ๋กœ ๋„˜์–ด๊ฐ€๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.


์ปดํฌ๋„ŒํŠธ์— ref ๋‹ฌ๊ธฐ#

๋ฆฌ์•กํŠธ์—์„œ๋Š” ์ปดํฌ๋„ŒํŠธ์—๋„ ref๋ฅผ ๋‹ฌ ์ˆ˜ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— ์žˆ๋Š” DOM ์„ ์ปดํฌ๋„ŒํŠธ ์™ธ๋ถ€์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์‚ฌ์šฉ๋ฒ•#

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

์ด๋ ‡๊ฒŒ ํ•œ ์ดํ›„์—, myComponent.handleClick , myComponent.input ๋“ฑ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€ ref(DOM ์š”์†Œ)์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

์Šคํฌ๋กค ๋ฐ•์Šค ์˜ˆ์ œ#

์ด์ œ ์Šคํฌ๋กค ๋ฐ•์Šค ์˜ˆ์ œ๋ฅผ ๋งŒ๋“ค์–ด ๋ณธ๋‹ค.

ScrollBox.js

import React, {Component} from 'react';
class ScrollBox extends Component {    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;

App ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” ๊ธฐ์กด ValidationSample ์„ ์ง€์šฐ๊ณ  ScrollBox ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•œ๋‹ค.

App.js

import React, {Component} from 'react';import ScrollBox from './ScrollBox';
class App extends Component {    render() {        return (            <div>                <ScrollBox />            </div>        );    }}
export default App;

2020-04-02-๋ฆฌ์•กํŠธ๋ฅผ-๋‹ค๋ฃจ๋Š”-๊ธฐ์ˆ -5์žฅ-ref-dom์—-์ด๋ฆ„-๋‹ฌ๊ธฐ-image-3

์ฝ”๋“œ๋ฅผ ์ €์žฅํ•˜๋ฉด, ์›น ๋ธŒ๋ผ์šฐ์ €์— ์Šคํฌ๋กค ๋ฐ•์Šค๊ฐ€ ์ž˜ ๋ Œ๋”๋ง๋œ๋‹ค.

์ด์ œ ๋ฒ„ํŠผ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ, ์Šคํฌ๋กค ๋ฐ•์Šค์˜ ์Šคํฌ๋กค๋ฐ”๋ฅผ ๋งจ ์•„๋ž˜์ชฝ์œผ๋กœ๋‚ด๋ฆฌ๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ๋งŒ๋“ค์–ด๋ณธ๋‹ค. ์ด ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด DOM ๋…ธ๋“œ๊ฐ€ ๊ฐ€์ง„ ๊ฐ’์„ ์‚ฌ์šฉํ•œ๋‹ค.

  • scrollTop : ์„ธ๋กœ ์Šคํฌ๋กค๋ฐ” ์œ„์น˜

  • scrollHeight : ์Šคํฌ๋กค์ด ์žˆ๋Š” ๋ฐ•์Šค ์•ˆ์˜ div ๋†’์ด

  • clientHeight : ์Šคํฌ๋กค์ด ์žˆ๋Š” ๋ฐ•์Šค์˜ ๋†’์ด


์Šคํฌ๋กค์„ ๋‚ด๋ ค์•ผ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๋ฐ•์Šค ๋‚ด๋ถ€์˜ ๊ธด ์ฝ˜ํ…์ธ  โ†’ scrollHeight ๊ธด ์ฝ˜ํ…์ธ ๋ฅผ์Šคํฌ๋กค๋ฐ”๋กœ ๊ฐ์‹ธ๋Š” ๋ฐ•์Šค โ†’ clientHeight


์Šคํฌ๋กค๋ฐ”์˜ ์œ„์น˜ scrollTop ์€ 0๋ถ€ํ„ฐ (๋ฐ•์Šค ๋‚ด๋ถ€์˜ ๊ธด ์ฝ˜ํ…์ธ  - ์Šคํฌ๋กค๋ฐ”๋กœ ๊ฐ์‹ธ๊ณ ์žˆ๋Š” ๋ฐ”๊นฅ์˜ ๋ฐ•์Šค)์˜ ํฌ๊ธฐ ๊ฐ’์„ ๊ฐ€์ง„๋‹ค. (๋ฐ”๊นฅ์˜ ๋ฐ•์Šค๊ฐ€ 300์ด๊ณ  ๋‚ด๋ถ€์˜ ์ฝ˜ํ…์ธ ๊ฐ€ 650 ์ด๋ผ๋ฉด ์Šคํฌ๋กค๋ฐ”์˜ ์œ„์น˜๊ฐ€ 0~350)

๋”ฐ๋ผ์„œ ์Šคํฌ๋กค๋ฐ”๋ฅผ ๋งจ ์•„๋ž˜์ชฝ์œผ๋กœ ๋‚ด๋ฆฌ๋ ค๋ฉด scrollHeight ์—์„œ clientHeight ๋ฅผ๋นผ๋ฉด ๋œ๋‹ค.

ScrollBox.js

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;

ScrollBox ์ปดํฌ๋„ŒํŠธ์—์„œ, this.box ๋กœ ์Šคํฌ๋กค๋ฐ”๊ฐ€ ์žˆ๋Š” ๋ฐ•์Šค DOM์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ณ , scrollToBottom ์ด๋ผ๋Š” ๋ฉ”์†Œ๋“œ๊ฐ€ ์ด DOM์— ์ ‘๊ทผํ•˜์—ฌ ์Šคํฌ๋กค๋ฐ”์˜ ์œ„์น˜ scrollTop ๋ฅผ ๋งจ ์•„๋ž˜๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค.

์ด๋ ‡๊ฒŒ ๋งŒ๋“ค๊ณ  ๋‚˜์„œ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์ธ App ์ปดํฌ๋„ŒํŠธ์—์„œ ScrollBox ์ปดํฌ๋„ŒํŠธ์— ref๋ฅผ๋‹ฌ๊ณ , ๋ฒ„ํŠผ์„ ๋งŒ๋“  ๋‹ค์Œ, onClick ์ด๋ฒคํŠธ์— ScrollBox ์ปดํฌ๋„ŒํŠธ์˜ ๋ฉ”์†Œ๋“œ์ธ scrollToBottom ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ํ•œ๋‹ค.

App.js

import React, {Component} from 'react';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;

2020-04-02-๋ฆฌ์•กํŠธ๋ฅผ-๋‹ค๋ฃจ๋Š”-๊ธฐ์ˆ -5์žฅ-ref-dom์—-์ด๋ฆ„-๋‹ฌ๊ธฐ-image-4

๋งจ ๋ฐ‘์œผ๋กœ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ์Šคํฌ๋กค๋ฐ”๊ฐ€ ๋งจ ๋ฐ‘์œผ๋กœ ์ด๋™ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.


๊ทธ๋Ÿฐ๋ฐ ์ฃผ์˜ํ•  ์ ์ด ์žˆ๋Š”๋ฐ, button ์š”์†Œ์— onClick ์ด๋ฒคํŠธ๋ฅผ ๋“ฑ๋กํ•  ๋•Œ, onClick = {this.scrollBox.scrollToBottom} ์œผ๋กœ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ๋ฌธ๋ฒ•์ƒ์œผ๋กœ ํ‹€๋ฆฐ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒ˜์Œ ๋ Œ๋”๋ง ๋  ๋•Œ๋Š” this.scrollBox ๊ฐ’์ด undefined ์ด๋‹ค. (ref ๋“ฑ๋ก์ด ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ด๋ฏ€๋กœ)

๋”ฐ๋ผ์„œ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ ๋ฌธ๋ฒ•์œผ๋กœ ์ƒˆ๋กœ์šด ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค๊ณ , ๊ทธ ๋‚ด๋ถ€์—์„œ this.scrollBox.scrollToBottom ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ, (์ด๋ฏธ ํ•œ๋ฒˆ ๋ Œ๋”๋ง์„ ๊ฑฐ์ณ this.scrollBox ๋ฅผ ์„ค์ •ํ•œ ์‹œ์ ) this.scrollBox.scrollTobottom ๊ฐ’์„ ์ฝ์–ด ์™€์„œ ์‹คํ–‰ํ•˜๋ฏ€๋กœ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.


์ •๋ฆฌ#

์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ DOM์— ์ง์ ‘ ์ ‘๊ทผํ•ด์•ผ ํ•  ๋•Œ๋Š” ref๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ํ•˜์ง€๋งŒ ref๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š”์ง€๋ฅผ ๋ฐ˜๋“œ์‹œ ๊ณ ๋ คํ•ด์•ผ ํ•œ๋‹ค.

์„œ๋กœ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋ผ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ๊ต๋ฅ˜ํ•  ๋•Œ ref๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋ผ๊ณ  ์˜คํ•ดํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ๊ทธ๋ ‡๊ฒŒ ํ•˜๋Š” ๊ฒƒ์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ตฌ์กฐ๋ฅผ ๊ผฌ์ด๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์œ„ํ—˜ํ•œ ๋ฐฉ๋ฒ•์ด๋‹ค. ๋”ฐ๋ผ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ต๋ฅ˜ํ•  ๋•Œ๋Š” ์–ธ์ œ๋‚˜ ๋ถ€๋ชจ - ์ž์‹ ํ๋ฆ„์œผ๋กœ ๊ต๋ฅ˜ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.


๊ฐ™์ด ์ฝ๊ธฐ#

Ref์™€ DOM - React