Reactivity Failing in my Examples - Help needed #1620
-
I put together some tests for different ways that I thought pinia reactivity should work, but I'm finding literally none of them work. Can anyone let me know what I need to change in order to turn on the 'magic' part of the reactivity? UPDATE: The reactivity was working fine, but...
You can see the original problem code at https://github.com/cefn/vitest-pinia-propagation/blob/1f8225f819cdbfd019c9068df4cdc1ad21710689/test/propagation.test.ts The now-working versions of three distinct state-propagation mechanisms are at https://github.com/cefn/vitest-pinia-propagation/blob/store-change-propagation/test/index.test.ts BackgroundIn this simplified scenario there is remotely loaded state held in a store. The problem is to construct some derived state that is itself reactive. The derived reactive structure should reflect the remote-loaded data when it appears. Downstream components will be watching the derived reactive state, not the original store. Here's an example which doesn't work, but there are four different approaches attempted in total which use different forms of reactivity wiring. They are const useComputedStore = defineStore("summary", () => {
const poemStore = usePoemStore();
const summary = computed(() => {
const { data } = poemStore;
if (data) {
return createSummary(data);
}
return null;
});
return {
summary,
};
}); The test suitein 1f8225f the tests all pass, (since this explicitly records what the problematic states are). However, they really shouldn't pass at all. In the test expectations that currently pass, you can see that all the states the reactive values settle to are junk. They don't reflect the changes which have taken place in the store I'm watching. In many cases they don't even reflect the initial state in the upstream store. In each case, the change to the store is ignored completely and never propagates to the target reactive value. You can see the tests passing by running
Getting helpI have tried to search for similar problems that people are experiencing, but they are mostly to do with destructuring (which I am doing inside computed as expected) or were offered guidance that looks an awful lot like the patterns I've implemented, but which don't work. I welcome any contributions and ideas as there is something fundamental I'm missing here. |
Beta Was this translation helpful? Give feedback.
Replies: 6 comments 3 replies
-
Not sure if that's the only thing but you have duplicated names in your stores: https://github.com/cefn/vitest-pinia-propagation/blob/2e1d5132ea02109c71cd6a26ac3dbfbcab71e8fe/test/propagation.test.ts#L76-L90 (both named summary) |
Beta Was this translation helpful? Give feedback.
-
Hey thanks for looking into the problem @posva ! I don't think this is the explanation sadly, although I have changed them since 1f8225f so as not to confuse people. The identical naming was deliberate. They are the same store, implemented in two different ways. Each store is used completely in isolation in its own test. Neither of them works, in the sense of propagating change from the Here are the two isolated sequences... |
Beta Was this translation helpful? Give feedback.
-
Oh, you are testing |
Beta Was this translation helpful? Give feedback.
-
Wonderful! With your help I'm making progress. I now have two of the four cases working. I can turn to a store with setup() as a workaround where I encounter failing change propagation. The examples that still don't work are now in the minimal suite_unhappy.ts. They have everything in common with I have hoisted the shared parts of the scenario into common files, and the passing implementations and tests are in a suite_happy.test.ts. You can see in the store-based cases that the change is propagating to the downstream stores now that I am consuming the upstream However, the unhappy tests assume that we can manipulate a reactive object, driven by notifications from either I thought this behaviour could be relied on, as its the way I would aim to author logic in a Vue component. I'm being careful to interact with the For reference, here's the full source of the unhappy cases in case anything leaps out to someone in the community that I got backwards, compared to the store-based versions that actually work. import { Pinia, createPinia } from "pinia";
import { describe, test, expect } from "vitest";
import { reactive, watch } from "vue";
import { createSummary, MappedPoem, usePoemStore } from "..";
import { emulateLoading, FIXTURE_POEM } from "./scenario";
/** Make a vue reactive object, watch() a pinia store and trigger explicit
* writes.
*/
function createReactiveWithWatch(pinia: Pinia) {
const poemStore = usePoemStore(pinia);
const mappedPoem = reactive<MappedPoem>({
summary: null,
});
watch(
() => poemStore.loading,
() => {
const { data } = poemStore;
if (data) {
mappedPoem.summary = createSummary(data);
}
mappedPoem.summary = null;
}
);
return mappedPoem;
}
/** Make a vue reactive object, $subscribe() a pinia store and trigger explicit
* writes.
*/
function createReactiveWithSubscribe(pinia: Pinia) {
const poemStore = usePoemStore(pinia);
const mappedPoem = reactive<MappedPoem>({
summary: null,
});
poemStore.$subscribe(() => {
const { data } = poemStore;
if (data) {
mappedPoem.summary = createSummary(data);
}
mappedPoem.summary = null;
});
return mappedPoem;
}
describe("Failure - tests pass but shouldn't - summary==='null' shows emulateLoading(...) doesn't propagate", () => {
test("Reactive with watch", async () => {
const pinia = createPinia();
const poemStore = usePoemStore(pinia);
const mapped = createReactiveWithWatch(pinia);
emulateLoading(poemStore, FIXTURE_POEM);
expect(mapped).toMatchInlineSnapshot(`
{
"summary": null,
}
`);
});
test("Reactive with subscribe", async () => {
const pinia = createPinia();
const poemStore = usePoemStore(pinia);
const mapped = createReactiveWithSubscribe(pinia);
emulateLoading(poemStore, FIXTURE_POEM);
expect(mapped).toMatchInlineSnapshot(`
{
"summary": null,
}
`);
});
}); |
Beta Was this translation helpful? Give feedback.
-
I would say the problem is that https://github.com/cefn/vitest-pinia-propagation/blob/43e8ab3/test/suite_unhappy.test.ts#L48 sets the state to null right away so I would say it's normal for tests to pass. |
Beta Was this translation helpful? Give feedback.
I would say the problem is that https://github.com/cefn/vitest-pinia-propagation/blob/43e8ab3/test/suite_unhappy.test.ts#L48 sets the state to null right away so I would say it's normal for tests to pass.
But these examples are getting hard to follow. I think you are almost there, if not, this could help: https://vuejs.org/api/reactivity-advanced.html#reactivity-api-advanced. Note that every pinia store is a reactive object itself and that the original refs of state are all stored at
pinia.state.value[storeId]
.