WEB/REACT

[React] ์Šคํฌ๋กค๋ฐ•์Šค ์ฝ”๋“œ์— ์œ„์•„๋ž˜ ์ด๋™ ๊ธฐ๋Šฅ ๊ตฌํ˜„

mingzoo 2021. 1. 2. 17:15

๐Ÿ“–๋ฆฌ์•กํŠธ๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ธฐ์ˆ ๐Ÿ“– ์ฑ…์— ์žˆ๋Š” ref์˜ˆ์ œ์ธ ์Šคํฌ๋กค ๋ฐ•์Šค ์กฐ์ž‘ ์ฝ”๋“œ๋Š” '๋งจ๋ฐ‘์œผ๋กœ'๋ผ๋Š” ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์ž๋™์œผ๋กœ ์Šคํฌ๋กค์„ ๋งจ ๋ฐ‘์œผ๋กœ ๋‚ด๋ ค๊ฐ€๊ฒŒ ํ•ด์ฃผ๋Š” ๋‚ด์šฉ์ด๋‹ค.

ํ•˜์ง€๋งŒ, ๋‚˜๋Š” ์—ฌ๊ธฐ์„œ ์‘์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ๋งˆ๋‹ค ์Šคํฌ๋กค ๋ฐ•์Šค๊ฐ€ ์œ„, ์•„๋ž˜๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ•˜๊ณ  ์‹ถ์—ˆ๋‹ค.

๋ฆฌ์•กํŠธ๋ฅผ ๋‹ค๋ฃฌ์ง€ ์–ผ๋งˆ ๋˜์ง€ ์•Š์•„ ์ฒ˜์Œ์—๋Š” ์ด๋ฏธ ์ž‘์„ฑ๋˜์–ด์ ธ ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ์–ด๋””์„œ๋ถ€ํ„ฐ ์† ๋Œ€์•ผ ๋ ์ง€ ๋ง‰๋ง‰ํ–ˆ์ง€๋งŒ, ์•ž์—์„œ ํ–ˆ๋˜ ์˜ˆ์ œ๋“ค์„ ์ด์šฉํ•ด์„œ ๊ณง์žฅ ๋ฐฉ๋ฒ•์„ ์ฐพ์•„๋‚ผ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

 

์ผ๋‹จ ์Šคํฌ๋กค์ด ๋‚ด๋ ค๊ฐ€์žˆ์„๋•Œ๋Š” ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์˜ฌ๋ผ์™€์•ผํ•˜๊ณ ,

์˜ฌ๋ผ๊ฐ€์žˆ์„ ๋•Œ๋Š” ๋‚ด๋ ค์™€์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ƒํ™ฉ์— ๋”ฐ๋ผ ๊ฐ’์ด ๋‹ฌ๋ผ์ง€๊ธฐ ๋•Œ๋ฌธ์— ์ด์— ๋Œ€ํ•œ ์ดˆ๊ธฐ๊ฐ’๋“ค์„ ์„ค์ •ํ•ด์ค˜์•ผํ•œ๋‹ค.

 

์ด์— ๋”ฐ๋ผ ์•ž ์žฅ์—์„œ์˜ ์˜ˆ์ œ๋“ค์„ ๋– ์˜ฌ๋ ค์„œ state์— ๋Œ€ํ•œ ์ดˆ๊ธฐ๊ฐ’์„ App.js์— ์„ค์ •ํ•ด์ฃผ์—ˆ๋‹ค.

state = {
    upDown: 'u', //์ฒ˜์Œ์— u๋ผ๊ณ  ์„ค์ •, ์ง€๊ธˆ ์œ„์น˜๊ฐ€ up์— ์žˆ๋‹ค๋Š” ๋œป
    value: 'To Bottom' //์ด์ œ ๋‚ด๋ ค๊ฐ€์•ผํ•œ๋‹ค๋Š” ๋œป์— ์„ค์ •
  }

 

์œ„์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ ๋ง์ด๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ๋ฒ„ํŠผ์„ ๋ˆ„๋ฆ„์— ๋”ฐ๋ผ state ๊ฐ’์ด u -> d ๋กœ, To Bottom -> To Top์œผ๋กœ ๋ฐ”๊ฟ”์ค„ ์ˆ˜ ์žˆ์–ด์•ผํ•œ๋‹ค.

์ด๋Ÿฐ ์„ค์ •์„ ํ•ด์ฃผ๊ธฐ ์œ„ํ•ด์„œ ํ•จ์ˆ˜ upOrDown์„ ๋งŒ๋“ค์–ด์„œ ์ด์šฉํ–ˆ๋‹ค.

 

upOrDown = () => {
    if (this.state.upDown === 'u') { //์›๋ž˜ ํ•ด๋‹น state๊ฐ€ u์˜€์œผ๋ฉด
      this.setState({
        upDown: 'd', // u->d
        value: 'To Top' //To Bottom -> To Top์œผ๋กœ ๋ฐ”๊ฟ”์คŒ
      });
    }
    else {
      this.setState({
        upDown: 'u',
        value: 'To Buttom'
      })
    }
  }

 

์ด upOrDownํ•จ์ˆ˜๋Š” '์ด๋™'์ด๋ผ๋Š” ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ์ค„๋•Œ๋งˆ๋‹ค state๊ฐ€ ๋ฐ”๊ปด์•ผ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ Œํ„ฐํ•จ์ˆ˜ ์•ˆ์— ์•„๋ž˜์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ ์ž‘์„ฑํ•ด์ค€๋‹ค.

 

render() {
    return (
      <>
        <ScrollBox ref={(ref) => this.scrollBox = ref} />
        <button onClick={() => {
          this.scrollBox.scrollChange(this.state.upDown);
          this.upOrDown(); //ํด๋ฆญ ๋ ๋•Œ๋งˆ๋‹ค state๊ฐ’ ๋ฐ”๊ฟ”์ฃผ๊ธฐ
        }}>
          ์ด๋™
        </button>
      </>
    );
  }

 

๊ทธ๋ ‡๋‹ค๋ฉด, ์Šคํฌ๋กค๋ฐ•์Šค๊ฐ€ ๊ตฌํ˜„๋˜์–ด์žˆ๋Š” ScrollBox.js ํŒŒ์ผ์€ ๋ฌด์—‡์„ ๋ฐ”๊ฟ”์ฃผ๊ณ  ์ถ”๊ฐ€ํ•ด์ค˜์•ผํ• ๊นŒ?

๋ฐ”๋กœ ์ฒ˜์Œ์— ๋ฐ›์•„์ง€๋Š” state๊ฐ’์— ๋”ฐ๋ผ ์œ„๋กœ ์˜ฌ๋ฆฌ๊ณ , ์•„๋ž˜๋กœ ์Šคํฌ๋กค์„ ๋‚ด๋ฆฌ๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด์•ผํ•œ๋‹ค. 

๋งค๊ฐœ๋ณ€์ˆ˜ param์„ ๋ฐ›๋Š”๋‹ค. ๋งŒ์•ฝ param์˜ ๊ฐ’์ด u๋ผ๋ฉด, ๋‚ด๋ฆฌ๋„๋ก ๋งŒ๋“ค๊ณ  ์•„๋‹ˆ๋ผ๋ฉด ์Šคํฌ๋กค์„ ์˜ฌ๋ ค์•ผํ•œ๋‹ค.

์ด๋Š” ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•˜๋ฉด ์ข‹์„๊นŒ?

 

//ScrollBox.js

scrollChange = (param) => {
        const { scrollHeight, clientHeight } = this.box;
        /*์œ„ ์ฝ”๋“œ๋Š” ๋น„๊ตฌ์กฐํ™” ํ• ๋‹น ๋ฌธ๋ฒ• ์‚ฌ์šฉ
        ๋‹ค์Œ ์ฝ”๋“œ์™€ ๋™์ผ
        const scrollHeight = this.box.scrollHeight;
        const clientHeight = this.box.clientHeight;
        */
        if (param === 'u') { //up์ผ๋•Œ ๋‚ด๋ฆด ์ค€๋น„
            this.box.scrollTop = scrollHeight - clientHeight;
        }
        else {
            this.box.scrollTop = 0;
        }
}

 

์œ„์™€ ๊ฐ™์€ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด์ฃผ์—ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ScrollTop์€ ์„ธ๋กœ ์Šคํฌ๋กค๋ฐ” ์œ„์น˜, ScrollHeight๋Š” ์Šคํฌ๋กค๋ฐ•์Šค์˜ ๋†’์ด๋กœ 650px์ด๊ณ , clientHeight๋Š” ์Šคํฌ๋กค์ด ์žˆ๋Š” ๋ฐ•์Šค์˜ ๋†’์ด๋กœ 300์„ ์˜๋ฏธํ•œ๋‹ค.

์Šคํฌ๋กค๋ฐ”๋ฅผ ๋ฐ‘์œผ๋กœ ๋‚ด๋ฆฌ๊ธฐ ์œ„ํ•ด์„œ๋Š” scrollHeight์—์„œ clientHeight๋ฅผ ๋‚ด๋ ค์ฃผ๋ฉด ๋˜๊ฒ ์ฃ ??

์œ„์™€ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ์™„์„ฑ๋œ ์ฝ”๋“œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค!

 

App.js

 

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

class App extends Component {
  state = {
    upDown: 'u',
    value: 'To Bottom'
  }
  upOrDown = () => {
    if (this.state.upDown === 'u') {
      this.setState({
        upDown: 'd',
        value: 'To Top'
      });
    }
    else {
      this.setState({
        upDown: 'u',
        value: 'To Buttom'
      })
    }
  }
  render() {
    return (
      <>
        <ScrollBox ref={(ref) => this.scrollBox = ref} />
        <button onClick={() => {
          this.scrollBox.scrollChange(this.state.upDown);
          this.upOrDown();
        }}>
          ์ด๋™
        </button>
      </>
    );
  }
}

export default App;

 

ScrollBox.js

 

import React, { Component } from 'react';

class ScrollBox extends Component {
    scrollChange = (param) => {
        const { scrollHeight, clientHeight } = this.box;
        /*์œ„ ์ฝ”๋“œ๋Š” ๋น„๊ตฌ์กฐํ™” ํ• ๋‹น ๋ฌธ๋ฒ• ์‚ฌ์šฉ
        ๋‹ค์Œ ์ฝ”๋“œ์™€ ๋™์ผ
        const scrollHeight = this.box.scrollHeight;
        const clientHeight = this.box.clientHeight;
        */
        if (param === 'u') { //up์ผ๋•Œ ๋‚ด๋ฆด ์ค€๋น„
            this.box.scrollTop = scrollHeight - clientHeight;
        }
        else {
            this.box.scrollTop = 0;
        }

    }
    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;

 

728x90