vue-router4 state객체로 페이지 사이 데이터 전달

LeeWonjin·2023년 5월 22일
5

문제해결

목록 보기
17/23

vue.js 3
vue-router 4 기준입니다.

페이지 사이의 데이터 전달

예전의 방법 : params

vue-router4에서 데이터를 전달하는 일반적인 방법은 두 가지이다.

  • query
  • params

이 중 params이라 함은 본래 url에 마치 path처럼 :id꼴로 값을 적어넣는 값이다. 예를 들어 https://example.com/1은 라우터 설정에 따라서는 데이터 1을 전달한 것이 될 수 있다. vue-router4에서 말하는 params도 url에 데이터를 적어넣어 다른 페이지로 전달하는 방식이 맞다.

그러나 많은 vue-router4사용자들은 이런 개념과는 다르게 params를 다뤘다.

vue-router4에서는 params을 전달할 때 url의 형태로 기술하는 대신 router.push method를 통해서도 params를 전달할 수 있다. url에 직접 값을 적거나 노출시키지 않고도 말이다.

<script setup>
import { useRouter } from 'vue-router';
const router = useRouter();
router.push({
	name : '다른페이지 이름',
    params : {
    	param이름 :,
        param이름 :,
    }
})
</script>

즉, vue-router4의 router.push({params:{}})를 사용하면 url에 데이터도 노출시키지 않고도 다른 페이지로 데이터를 넘기는 것이 가능했으며 그런 식으로 많이 이용돼왔다. (심지어는 params를 props로 자동으로 넘기는 것도 된다)

url에 데이터를 노출시키지 않고 페이지간에 데이터를 전달하는 방법을 검색하면 앞서 말한 것과 같은 방법이 정말 많이 검색된다. 그러나 지금은 vue-router4가 그 사용법을 지원하지 않는다. bad-practice라고 판단했기 때문이다. 아래 내용을 보면 알 수 있다.

https://github.com/vuejs/router/blob/main/packages/router/CHANGELOG.md#414-2022-08-22

대안 : state객체

https://developer.mozilla.org/en-US/docs/Web/API/History/state

기존의 코드가 아래와 같았다고 하자

// router.js의 일부
const route = [
	{
    	path : '/another/page'
        name : 'anotherPage',
        component : AnotherPage,
        props : true,
    }
]

// App.vue의 일부
<script setup>
function goAnotherPage() {
	router.push({
		name: 'AnotherPage',
		param: {
			dataObj : { a:1, b:'string';, c:true },
		},
	});
}
</script>

// AnotherPage.vue의 일부
<script setup>
const props = defineProps({
	dataObj : {
    	type : Object,
    },
});
console.log(props.dataObj); // { a:1, b:'string';, c:true }
</script>

아래와 같이 변경하면 된다.

  • push()인수 객체의 paramsstate로 바꾼다
  • 받는 쪽에서는 props나 route가 아니라 history.state로 받는다.
// router.js의 일부
const route = [
	{
    	path : '/another/page'
        name : 'anotherPage',
        component : AnotherPage,
        // 참고 -- props:true는 이제 필요가 없다.
    }
]

// App.vue의 일부
<script setup>
function goAnotherPage() {
	router.push({
		name: 'AnotherPage',
		state: { // params가 state로 바뀌었다.
			dataObj : { a:1, b:'string';, c:true },
		},
	});
}
</script>

// AnotherPage.vue의 일부
<script setup>
const { dataObj } = history.state; // 이렇게 받는다.
console.log(dataObj); // { a:1, b:'string';, c:true }
</script>

state객체 값을 설정할 때 Error with push/replace State경고 발생

상황

아래 오류가 뜨면서 새로고침됨.

[Vue Router warn]: Error with push/replace State 
warn	@	vue-router.mjs:35
changeLocation	@	vue-router.mjs:519
push	@	vue-router.mjs:553
finalizeNavigation	@	vue-router.mjs:3331
(anonymous)	@	vue-router.mjs:3207
Promise.then (async)		
pushWithRedirect	@	vue-router.mjs:3174
push	@	vue-router.mjs:3099
handleModifyTimeData	@	ReservationDetailView.vue:356
callWithErrorHandling	@	runtime-core.esm-bundler.js:173
callWithAsyncErrorHandling	@	runtime-core.esm-bundler.js:182
invoker	@	runtime-dom.esm-bundler.js:345

원인

state객체에는 vue반응형 Proxy객체를 넣으면 에러가 난다.

해결

적당히 js의 본래 자료형으로 만들어 실어보내면 된다.

<script setup>
import {ref} from 'vue';
const data = ref([1,2,3]);

function 에러가_발생하는_함수() {
	router.push({
		name: '다른 페이지 이름',
		state: {
			data: data.value,
		},
	});
}

function 에러가_해결된_함수() {
	const mappedData = data.value.map(item => item);
	router.push({
		name: '다른 페이지 이름',
		state: {
			data: mappedData,
		},
	});
}
</script>
profile
노는게 제일 좋습니다.

0개의 댓글