API통신의 response값을 특정 컴포넌트의 props 로 전달할 때, props 데이터가 실시간으로 변경되지 않는 이슈가 발생하였다.
정확히 말하자면, 데이터가 한타임씩 씹힌 채로 하위컴포넌트를 랜더링하는 상황이었다.
console.log() 로 확인해보니 데이터는 정상적으로 들어있었으나, 컴포넌트로 넘어온 props.printData 는 이전 console.log에서 찍힌 값이 출력되고 있었다. 이러한 상황이 발생한 이유로 크게 2가지를 의심해보았고, 한가지 방법으로 해결할 수 있었다.
// 상위 컴포넌트
<template>
<print-page :print-data="state.printData" />
</template>
<scrip setup>
import Printpage from '@/printView/printPage'
const saveRowList = async () => {
store.commit('loadingStart')
try {
const { data } = await Api.save(state.rowData)
state.printData = data
console.log(state.printData) // printed what i expexted
printJS(state.printStyle) //화면 프린트 실행 코드
} catch (e) {
console.log(e)
} finally {
store.commit('loadingEnd')
}
}
<script>
-> 상위에서 넘겨준 props 데이터를 state 변수가 computed로 감지하도록 수정
//하위 컴포넌트
<template>
<div>{{state.propsData}}</div>
</template>
<scrip setup>
import {reactive, computed} from 'vue'
const state = reactive({
propsData : computed(()=> props.printData)
})
const props = definedProps({
printData : {
type : Object,
default : () => {
return {}
}
}
})
<script>
** 하지만, 동일한 이슈가 지속되었고 다른 방법을 찾아보았다.
-> try...catch 문법을 활용하여 코드를 동기적으로 실행한 뒤 finally 구문에서 데이터 할당
//상위 컴포넌트
<script setup>
const saveRowList = async () => {
store.commit('loadingStart')
try {
const { data } = await Api.save(state.rowData)
state.printData = data
} catch (e) {
console.log(e)
} finally {
printJS(state.printStyle) // --> 코드 위치 변경
store.commit('loadingEnd')
}
}
<script>
** 이슈가 해결되었다. 아마도, 시점차이로 인해 하위컴포넌트가 전달받은 props데이터를 실시간으로 반영하지 못했던 게 원인이었던 듯 싶다.
try...catch 문은 에러발생 시, 스크립트가 죽었을 때 화면이 비정상적으로 렌더링 되는 것을 방지하고 사용자에게는 상황에 어울리는 UI를 제공할 수 있는 문법이다.
try...catch구문은 동기적으로 실행되기 때문에, try {} 블록 내의 모든 코드가 에러없이 실행된 후에(API 통신의 response 값이 정상적으로 할당) finally(생략가능) 블록이 순차적으로 실행되므로 finally {} 블록에서 프린트로직을 실행시킨다면,
이 외에도, nextTick으로 DOM이 update될 때까지 기다린 뒤에 화면을 그리도록 하는 방법도 존재한다. 따라서, 다음 포스팅은 동일한 이슈를 nextTick()으로 해결하는 내용을 작성하도록 하겠다.