반응형

vue prop data 를 사용하다가

 

Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders

이 오류를 본 적이 있다.

 

이 오류가 난 경우는 props data 를 받고 이 props 데이터를 변경해주었더니 생긴 오류다.

이 props 데이터를 위로 올리고 이 올린 데이터를 또 props 로 내려서 하위 자식에서 쓰려했더니 생긴 오류다.

 

props 에 대한 vue 의 공식 문서 설명이다.

일반적으로 prop을 변경시키고 싶은 유혹을 불러 일으킬 수있는 두 가지 경우가 있습니다.
1. 이 prop는 초기 값을 전달 하는데만 사용되며 하위 컴포넌트는 이후에 이를 로컬 데이터 속성으로 사용하기만 합니다.
2. prop는 변경되어야 할 원시 값으로 전달됩니다.

https://kr.vuejs.org/v2/guide/components.html#%EB%8B%A8%EB%B0%A9%ED%96%A5-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%9D%90%EB%A6%84

- vue 공식문서

 

자식으로 내려온 props 데이터를 고치면 부모 데이터도 수시로 바뀐다고 생각했지만, 데이터 흐림이 단방향이므로 하위 데이터를 바꾼다 하더라도 부모의 데이터를 바꿀수 없었다..

 

그래서 eventBus 를 통해서 부모의 데이터를 바꿔준다.

 

여기까지는 괜찮지만 초기 렌더링시에 문제가 생길 수 있다.

이유는 데이터가 비동기적인 데이터를 가져오기 때문인데, 

 

인스턴스 생성 순서는 부모 -> 자식이며, 마운팅 순서는 자식->부모 

이기 떄문에 비동기적으로 데이터를 부모에서 자식으로 줄때 문제가 생긴다. 이런 문제를 아래 코드를 예시로 해결하자.

 

 

비동기적인 상황에서

부모가 자식에게 데이터를 내려주고 부모 컴포넌트가 바뀐데이터를 받는 방법

부모 컴포넌트

<template>
<date-picker
:propDate="dateData"
v-on:update:dateSettting="setDate"
/>
</template>
<script>
export default {
  data () {
    return {
    	dateData: '' // 비동기 데이터
    }
  },
  methods: {
    get () { // 비동기호출데티어
        http
          .get('sampleUrl')
          .then(response => {
            this.dateData = response.data
          })
          .catch(e => {
           
          })
          .finally(() => {
          })
      }
    },
    setDate (value) { // 이벤트버스 호출시 실행
      this.dateData = value
    },
  }  
</script>

자식 컴포넌트

<template>
  <div >
    <datepicker
      class="datepicker"
      placeholder="예) 2019-07-27"
      :language="languages['ko']"
      format="yyyy-MM-dd"
      ref="openDate"
      v-model="date"
    />
  </div>
</template>

<script>
import Datepicker from 'vuejs-datepicker/dist/vuejs-datepicker.esm.js'
import * as lang from 'vuejs-datepicker/dist/locale'

export default {
  props: {
    propDate: String
  },
  data () {
    return {
      languages: lang
      // date: this.propDate // 하위 컴포넌트부터 값이 정해지므로 초기렌더링시 값이 안내려온다
    }
  },
  computed: {
    date: {
      get () {
        console.log('get')
        return this.propDate
      },
      set (newVal) {)
        this.$emit('update:dateSettting', newVal)
      }
    }
  },
  components: {
    Datepicker
  }
}
</script>

 

부모가 먼저 생기지만 마운팅 순서는 자식이 먼저이기 때문에 초기 렌더링시 값이 비어있다.

이러한 이유로 위 코드에서 처럼 자식에 props 데이터를 자식 데이터에 연결해서 쓸때 data() 속성을 사용하지 않고,

computed 를 통해서 사용해야 한다.

 

이런 비동기적인 props를 전달받는 상황이라면 computed속성을 사용하는 것이 맞다

 

참고문헌

https://kjwsx23.tistory.com/357
[Vue.js] props로 받은 데이터를 data로 사용하기

https://stackoverflow.com/questions/45943682/how-to-initialize-data-properties-with-prop-values
How to Initialize Data Properties with Prop Values

 

반응형

+ Recent posts