반응형
vuex의 "모사" 돌연변이
import { remoteSettings } from 'somewhere';
const store = {
state: {
view: {
foo: true
}
},
mutations: {
toggleFoo(state) {
state.view.foo = !state.view.foo;
}
},
actions: {
async toggleFoo({ state, commit }) {
commit('toggleFoo');
await remoteSettings.save(state);
}
}
};
나한테 이런 간단한 가게가 있다고 말해줘. toggleFoo
동작은 돌연변이를 적용한 다음 비동기 호출로 새 상태를 저장한다.그러나, 만약remoteSettings.save()
호출 실패, 저장소에 있는 로컬 설정과 원격 설정이 동기화되지 않음.내가 이 행동에서 꼭 이루고 싶은 것은 다음과 같은 것이다.
async toggleFoo({ state, commit }) {
const newState = simulateCommit('toggleFoo');
await remoteSettings.save(newState);
commit('toggleFoo');
}
나는 실제로 저지르지 않고 새로운 주를 얻고 싶다.원격 호출이 성공하면 실제로 스토어를 업데이트하겠다.그렇지 않으면 그대로 있을 것이다.
(변이함수의 논리를 실제로 복제하지 않고) 이것을 달성하는 가장 좋은 방법은 무엇일까?어쩌면 "undo"?잘 모르겠어.
이렇게 하는 한 가지 방법은 다음과 같다: (실수를 바로잡은 @Bert의 신용)
다음을 사용하여 이전 상태 저장
const oldState = state;
돌연변이를 일으키기 전에 말이야비동기 호출을 다음으로 줄임
try-catch
막다만약
remoteSettings
실패하면 에 처형을 넘길 것이다.catch
막다캐치 블록에서 돌연변이를 일으켜 상태를 재설정한다.
예:
const store = {
state: {
view: {
foo: true
}
},
mutations: {
toggleFoo(state) {
state.view.foo = !state.view.foo;
},
resetState(state, oldState){
//state = oldState; do not do this
//use store's instance method replaceState method to replace rootState
//see : https://vuex.vuejs.org/en/api.html
this.replaceState(oldState)
}
},
actions: {
async toggleFoo({ state, commit }) {
const oldState = JSON.parse(JSON.stringify(state)); //making a deep copy of the state object
commit('toggleFoo');
try {
await remoteSettings.save(newState);
//commit('toggleFoo'); no need to call this since mutation already commited
} catch(err) {
//remoteSettings failed
commit('resetState', oldState)
}
}
}
};
@VamsiKrishna로부터 코드를 빌려서(고맙다) 나는 대안을 제시한다.내 생각에, 당신은 서버에 변경사항을 보내고 성공에 대한 로컬 상태를 업데이트하고 싶어 한다.여기 일하는 예가 있다.
논리 중복을 방지하려면 변경 사항을 함수로 추상화하십시오.
console.clear()
const remoteSettings = {
save(state){
return new Promise((resolve, reject) => setTimeout(() => reject("Server rejected the update!"), 1000))
}
}
function updateFoo(state){
state.view.foo = !state.view.foo
}
const store = new Vuex.Store({
state: {
view: {
foo: true
}
},
mutations: {
toggleFoo(state) {
updateFoo(state)
},
},
actions: {
async toggleFoo({ state, commit }) {
// Make a copy of the state. This simply uses JSON stringify/parse
// but any technique/library for deep copy will do. Honestly, I don't
// think you would be sending the *entire* state, but rather only
// what you want to change
const oldState = JSON.parse(JSON.stringify(state))
// update the copy
updateFoo(oldState)
try {
// Attempt to save
await remoteSettings.save(oldState);
// Only commit locally if the server OKs the change
commit('toggleFoo');
} catch(err) {
// Otherwise, notify the user the change wasn't allowed
console.log("Notify the user in some way that the update failed", err)
}
}
}
})
new Vue({
el: "#app",
store,
computed:{
foo(){
return this.$store.state.view.foo
}
},
mounted(){
setTimeout(() => this.$store.dispatch("toggleFoo"), 1000)
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.9/vue.js"></script>
<div id="app">
<h4>This value never changes, because the server rejects the change</h4>
{{foo}}
</div>
참조URL: https://stackoverflow.com/questions/47737612/simulate-mutations-in-vuex
반응형
'Programing' 카테고리의 다른 글
VueJS/VueX 최대 통화 스택 크기를 초과함 (0) | 2022.04.12 |
---|---|
오류: /Users/name/Desktop/blognewtonmcvue/store에서 ESLint 구성을 찾을 수 없음 (0) | 2022.04.12 |
VueJS + VUEX + 소방 기지:소방 기지를 어디에 설치할 것인가? (0) | 2022.04.12 |
VueJS에서 v-for 지시문을 사용하여 여러 루트 요소를 렌더링하는 방법 (0) | 2022.04.12 |
Vue 3에서 Vuex 4로 데이터를 설정하지 않음 (0) | 2022.04.12 |