React

row 번호 자동으로 뽑아주는 함수 만들기

빡새 2023. 4. 4. 09:00

 

|  번호  |  제목  |  내용  |
---------------------------
    1      key1    data1
    2      key2    data2
    3      key3    data3
    4      key4    data4
    5      key5    data5
    6      key6    data6
    7      key7    data7
    8      key8    data8
    9      key9    data9
    10     key10   data10
    11     key11   data11
    12     key12   data12
    ......
    ....
    ..

- 만들고 싶은 기능 - 

만약 위와 같은 테이블을 만들어야 한다고 생각해 보자.
 제목과 내용에 들어가는 값들은 어쨌든 key 값들이니 일일이 넣어줘야 할 것이다.
 이 부분은 어쩔 수 없으니 넘어가자.

하지만 번호까지 1,2,3,4... 일일이 쓰는 건 너무 프로그래머로서 귀찮다.
또 항목 순서가 바뀌거나, 항목이 추가/삭제되면 번호를 하나씩 밀려서 모두 바꿔줘야 한다.
유지보수까지 생각하니 더욱 귀찮다.

 

 

- 방법 구상 -

번호를 자동으로 뽑아주는 방법을 생각해 봤다.
for문 같은 걸 쓸 수도 없다.
그러려면 반복문을 돌리면서 row 를 하나씩 불러와서 번호를 넣어줘야 하는데,
그러기에는 항목마다 데이터 타입이나 이벤트 처리도 각각 다르기 때문이다.

그래서 약간 클래스 변수처럼 쓰는 방법을 생각해 봤다.
화면 전체에서 행 번호 변수 rowNum 을 하나 갖는다.
이 행 번호 변수는 함수 getRowNum() 을 통해서 받아올 수 있다.
대신 번호를 받아올 때마다 번호가 1씩 증가하도록 만든다.
그러면 render() 함수가 실행되면서 화면을 그리는 동안에 그 안에서 getRowNum() 가 실행될 것이다.
행 하나를 그릴 때마다 getRowNum() 를 실행할 것이고,
그때마다 행 번호 변수 rowNum 은 1씩 자동으로 증가할 것이다.

 

 

- 코드 - 

class MyTable = {
    _rowNum = 0;
    getRowNum() {
        this._rowNum = this._rowNum + 1;
        return this._rowNum;
    }

    // ...

    render() {
        this._rowNum = 0;
        
        return (
            <table>
                <tbody>
                    <tr>
                        <th>{this.getRowNum()}</th>
                        <th>{"key1"}</th>
                        <th>{"data1"}</th>
                    </tr>
                    <tr>
                        <th>{this.getRowNum()}</th>
                        <th>{"key2"}</th>
                        <th>{"data2"}</th>
                    </tr>
                    <tr>
                        <th>{this.getRowNum()}</th>
                        <th>{"key3"}</th>
                        <th>{"data3"}</th>
                    </tr>
                </tbody>
            </table>
        );
    }
}

 



이게 될까...? 하면서 반신반의 하며 실행해 봤는데 잘 된다.
'이게 될까...?' 라며 미심쩍어 했던 이유는 render() 함수 안에서
변수를 조작하는 로직이 실행되고 있기 때문이다.
render() 함수 안에서는 되도록 화면을 그리는 작업 외에는 다른 작업을 수행하지 않는 것이 좋다.
그 이유는 사이드 이펙트 때문이다.
https://velog.io/@superlipbalm/blogged-answers-a-mostly-complete-guide-to-react-rendering-behavior

// 렌더 로직은 다음을 수행해서는 안 됩니다.
> 기존 변수 및 객체를 변경할 수 없습니다.
> Math.random() 또는 Date.now() 와 같은 임의의 값을 생성할 수 없습니다.
> 네트워크 요청을 할 수 없습니다.
> state 업데이트를 큐에 추가할 수 없습니다.

// 렌더 로직은 다음을 수행할 수 있습니다.
> 렌더링 도중 새로 생선된 객체 변경
> 오류 발생
> 캐시된 값과 같이 아직 생성되지 않은 데이터에 대한 '지연 초기화'

https://gist.github.com/sebmarkbage/75f0838967cd003cd7f9ab938eb1958f

render() 함수는 어쨌든 '순수하게' 화면을 그리는 역할만 해야 하고,
화면의 다른 상태나 변수를 건드리면 안 된다.
어쨌든... 에러도 안 나고 심각한 사이드 이펙트처럼 보이지는 않으므로 그냥 쓰기로 했다.



추가)

this._rowNum = 0;
render() 함수 안에서 위 구문을 실행해야 한다.
render() 를 실행할 때마다 _rowNum 의 값을 0으로 초기화하는 역할이다.
왜냐하면 state 나 props 가 바뀌면 render() 함수를 계속 부르는데,
render 를 다시 부르면 행 번호 숫자가 이어서 증가하기 때문이다.
unmount 되었다가 페이지가 새로 로드되지 않는 이상 클래스 변수는 초기화되지 않는다.
따라서 render() 를 부를 때마다 행 번호를 0부터 시작하도록 초기화해줘야 한다.

 

 - 230223 -

반응형