프로그래밍/FE engineering

[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated:

toeun 2021. 4. 15. 14:07

Vue.js 에서 부모 컴포넌트와 하위 컴포넌트 데이터 전달을 위한 props 를 사용하다가 console에서 하기와 같은 오류를 마주친적이 있다.

 

Vue warn에 대한 DevTools console 메시지 캡처

 

사실 그동안 무심코 지나쳤다가.. 저런 warning도 지나치지 말자는 다짐으로 이번 기회에 고쳐본다.

 

나 같은 경우는,

부모 컴포넌트에서 자식 컴포넌트에게 "files"라는 data를 props로 전달하는데,

자식 컴포넌트에서 props로 받은 files를 직접 변경하는 코딩을 하였다.

저 console 메시지를 직역하면 부모 컴포넌트에서 이 props를 re-rendering하여 값을 다시 엎어쓸수도 있으니,

자식 컴포넌트에서는 props로 전달받은 값을 복사하여 사용하라는 말이다.

 

즉, 부모 컴포넌트에서 전달하는 props는 단방향으로써, 자식 컴포넌트에서 변경해도 부모 컴포넌트에게 영향이 가지 않으니 props는 원시값으로 전달만 받고 자식 컴포넌트에서는 로컬 데이터 속성(data, computed)으로 사용해야 한다.

 

사실 이 부분을 무시해도 동작은 하겠지만,

Vue의 라이프사이클 및 상태 관리 측면에서는 무시했다가 개발자도 모르겠는 원인모를 이유의 버그로 보여지게 될지도 모르겠다.

 

소스 수정은 하기와 같이 진행하였다.

 

 

# 부모 컴포넌트(변경전)

<common-file-upload :file="profileImageInfo"
                    :multiple="false"
>
</common-file-upload>

# 자식 컴포넌트(변경전)

    props: {
      file: {
        default: []
      },
      multiple: {
        default: true,
      },
    },
    
(생략..)

    methods: {
      onSelectFile: function (e) {
        console.log(e)
        const files = e.files;
        
        const fileInfo = e.files[0]
        
        // 문제되는 부분
        this.file = fileInfo
      },
    }

 

# 부모 컴포넌트(변경후)

<common-file-upload :file="profileImageInfo"
                    :multiple="false"
                    @setFile="fnSetFile"
>
</common-file-upload>

(생략..)

methods: {
  fnSetFile: function(file) {
  	this.profileImageInfo = file
  },
}

# 자식 컴포넌트(변경후)

    props: {
      file: {
        default: []
      },
      multiple: {
        default: true,
      },
    },
    
(생략..)

    methods: {
      onSelectFile: function (e) {
        console.log(e)
        const files = e.files;
        
        const fileInfo = e.files[0]
        
        // 문제되는 부분
        // this.file = fileInfo
        // 문제 해결
        this.$emit('setFile', files)
      },
    }

 

앞으로 이러한 warning은 더이상 마주치지 않겠다ㅎ