본문 바로가기
JavaScript/React

[ReactJS] add component in list

by 혀나Lee 2016. 12. 29.

동적으로 리스트 안의 값을 추가하여 보여줘야 하는 경우가 있다. ReactJS 에서는 render() 안의 값을 동적으로 보여주기 위해서는 state 를 이용해야 한다.


import React from 'react';

import TmpComponent from './TmpComponent');



export default class TestClass extends React.Component {

    constructor(props) {

        super(props);

        this.state = {

resultAjax: [],

tmpState: [],

checked: []

        }

    }


    componentDidMount() {

        // Ajax 호출

        ...

for (..) {

checked[i] = false;

this.setState({resultAjax: response.resultData, checked: checked});

}

...

    };


    render() {

        let {tmpState} = this.state;


this.state.resultAjax.map((data, i)) => {

tmpState[i] = (

<TmpComponent

key={`tmp${i}`}

checked={checked[i]}

/>

)

}

        

        return (

            {tmpState}

        )

    }

}


위와 같이 render() 함수 안에서 한번만 만들 때는 문제없이 동적으로 리스트가 추가된 것을 확인할 수 있을 것이다. 다만, 이 때의 동적이란 의미는 componentDidMount() 함수에서 Ajax 호출 결과로 반환된 데이터의 리스트에만 국한된다.


하지만, 저렇게 만들고 나서 어떤 버튼 이벤트를 통해 또 추가하고 싶을 경우에는 어떻게 될까?

물론, 위와 비슷하게 만들면 될 것이다. 아래를 참고하자.


addComponent = () => {

let {checked, tmpState} = this.state;

let tmpCount = tmpState.length;


checked[tmpCount] = false;

tmpState[tmpCount] = (

<TmpComponent

key={`tmp${i}`}

checked={checked[tmpCount]}

/>

);

};


위와 같이 어떠한 이벤트에 addComponent() 함수를 호출하면 아마 화면 상에는 TmpComponent가 잘 추가되어 나올 것이다.

하지만, 내가 TmpComponent 컴포넌트의 checked 속성에 CSS를 변경해 주는 등의 이벤트를 만들어 놨을 경우에 문제가 생긴다.

render() 함수 내에서 동적으로 추가된 컴포넌트들은 CSS 변경이 잘 적용되지만 addComponent() 함수에서 새로 추가된 컴포넌트들은 CSS 변경이 안될 것이다.


addComponent() 함수와 같이 처리하고 싶은 경우가 있다면 아래의 코드처럼 수정을 하면 잘 될 것이다.


import React from 'react';

import TmpComponent from './TmpComponent');



export default class TestClass extends React.Component {

    constructor(props) {

        super(props);

        this.state = {

resultAjax: [],

tmpState: [],

checked: []

        }

    }


    componentDidMount() {

        // Ajax 호출

        ...

for (..) {

checked[i] = false;

this.setState({resultAjax: response.resultData, checked: checked});

}

...

    };


    addComponent = () => {

let {checked, tmpState} = this.state;

let tmpCount = tmpState.length;


checked[tmpCount] = false;

tmpState[tmpCount] = (

<TmpComponent

key={`tmp${i}`}

checked={checked[tmpCount]}

/>

);

    };

    

    cloneTmpState = (child, index) => {

        const {checked} = this.state;


        return React.cloneElement(child, {

checked: checked[index],

...

// 새로 추가하고 싶은 속성들

});

    };


    render() {

        let {tmpState} = this.state;


this.state.resultAjax.map((data, i)) => {

tmpState[i] = (

<TmpComponent

key={`tmp${i}`}

checked={checked[i]}

/>

)

}

        

        return (

{tmpState}

{React.Children.map(tmpState, (child, index) => {

return this.cloneTmpState(child, index)

})}

        )

    }

}


한 번 컴포넌트로 생성된 속성은 state 값이 바뀌어도 인식을 하지 못한다. 따라서, cloneElement() 를 이용하여 render() 가 다시 그려질 때, 속성값을 새로 추가해주면 된다.

'JavaScript > React' 카테고리의 다른 글

[ReactJS] scroll to top  (0) 2017.07.31
[React] 속도 향상  (0) 2017.07.25
[ECMAScript6] get max number in list  (0) 2016.12.28
[React] window.print  (0) 2016.11.30
[React] jspdf, jspdf-autotable  (1) 2016.11.29

댓글