Creating a derived reducer for a DynMapReducer

Do you have an example of how to make a derived reducer for a reducer that's not part of a TJSDcoument?
const reducer = getContext("reducer");
let derived = [];

if (enableGrouping) {
const filters = filterBy[compendiumType];
const property = `system.${groupBy[compendiumType]}`;

for (const filterValue of filters) {
const dr = $reducer.derived.create(`${filterValue}`);
console.log(dr);

dr.filters.add((doc) => doc[property] === filterValue);
derived.push(dr);
}

derived = derived;
}
const reducer = getContext("reducer");
let derived = [];

if (enableGrouping) {
const filters = filterBy[compendiumType];
const property = `system.${groupBy[compendiumType]}`;

for (const filterValue of filters) {
const dr = $reducer.derived.create(`${filterValue}`);
console.log(dr);

dr.filters.add((doc) => doc[property] === filterValue);
derived.push(dr);
}

derived = derived;
}
16 Replies
Nekro Darkmoon
Nekro DarkmoonOP•12mo ago
derived[0] is an instance of DynMapReducerDerived and the data does exist on it but doing [...derived[0]] or [...reducer.derived.get("somename")] spits out an empty array
TyphonJS (Michael)
TyphonJS (Michael)•12mo ago
Just as an aside to start you can create a subclass of DynMapReducerDerived and this will make the code a bit nicer. I gather you might also be in control of the main DynMapReducer from the context reducer. Here is an example from the tests of DynMapReducer showing how to create a custom reducer and class based derived reducers. https://github.com/typhonjs-svelte/dynamic-reducer/blob/main/test/src/runner/tests/map/DerivedTests.js#L161-L252 This will only make the code a bit tidier, but we'll have to take a look at any of the specific aspects that you do or do not see from there. An interesting note is that a custom derived reducer is associated by passing in the class and not an instance. It appears you are setting up dynamic filters based on some criteria const filters = filterBy[compendiumType]; That may make things a bit harder to isolate in a custom class for a derived reducer. Just out of general interest. I think it's possible that dr.filters.add((doc) => doc[property] === filterValue); is not triggering an update for the index used behind the scenes. After you add the filter try:
dr.filters.add((doc) => doc[property] === filterValue);
dr.index.update(true);
derived.push(dr);
dr.filters.add((doc) => doc[property] === filterValue);
dr.index.update(true);
derived.push(dr);
Do report back if [...derived[0]] has the proper values you expect.
Nekro Darkmoon
Nekro DarkmoonOP•12mo ago
Will try that in a bit Yeah I'm still doing rough drafts trying to get it to work Will tidy it up into classes once it works ^^
TyphonJS (Michael)
TyphonJS (Michael)•12mo ago
It should automatically perform an index update after adding a filter, but there is a chance that it isn't. The explicit dr.index.update(true) forces an update. Possibly it fixes the issue, but a little investigation warranted to verify what is going on.
Nekro Darkmoon
Nekro DarkmoonOP•12mo ago
that did infact work 😄
TyphonJS (Michael)
TyphonJS (Michael)•12mo ago
Hmm... I'll have to review the dynamic reducer code to suss out if that behavior is intended. This line should trigger an index update automatically: https://github.com/typhonjs-svelte/dynamic-reducer/blob/main/src/common/adapter/AdapterFilters.ts#L175 subscribeCount should be 0 and filters.length should be 1 in the add invocation. Perhaps you can drop a console.log into node_modules\@typhonjs-fvtt\runtime\_dist\svelte\store\reducer\index.js. Search for the add function, but where you need to insert the log statement is line 382. Do a production build to ensure that the temporary log statement is picked up. Perhaps, you can also provide a link to the code that sets up the reducer. It's a bit suspect executing the code initially posted in the OP as this is presumably in a Svelte component. I know you are just trying to get something to work, but it would be great to get more knowledge on what you are doing exactly.
Nekro Darkmoon
Nekro DarkmoonOP•12mo ago
sorry for the late reply The code isn't on a public repo but I can post the reducer bit here
function getDocuments(docList) {
// Sort the documents into alphabetical order
docList.sort((a, b) => a.name.localeCompare(b.name));

const validDocs = new Map();
docList.forEach((doc) => validDocs.set(doc._id, doc));
return validDocs;
}

let reducer = new DynMapReducer();
reducer.setData(getDocuments([...document.index]), true);
function getDocuments(docList) {
// Sort the documents into alphabetical order
docList.sort((a, b) => a.name.localeCompare(b.name));

const validDocs = new Map();
docList.forEach((doc) => validDocs.set(doc._id, doc));
return validDocs;
}

let reducer = new DynMapReducer();
reducer.setData(getDocuments([...document.index]), true);
TyphonJS (Michael)
TyphonJS (Michael)•12mo ago
Yeah... Go for it... Chances are when adding / removing a filter.. A force update should occur and that is an easy fix. Might just need to add true here: if (subscribeCount < filters.length) { this.#indexUpdate(true); }
Nekro Darkmoon
Nekro DarkmoonOP•12mo ago
This is how the reducer is being set up I was initally making a reducer of TJSDocuments but that wasn't needed since the documents won't be edited while viewing them for context the documents here are compendium documents so there's nothing in TRL to support that which is why the reducer approach
TyphonJS (Michael)
TyphonJS (Michael)•12mo ago
I'll definitely take a look before shipping the next TRL and verify things in the dynamic reducer tests.
Nekro Darkmoon
Nekro DarkmoonOP•12mo ago
👌 ty yeah we're kind of going real hard on the svelte side of things with converting anything we can to svelte 😄
TyphonJS (Michael)
TyphonJS (Michael)•12mo ago
And indeed it's a good idea to be mindful of bulk TJSDocument creation because it will add a hard link / callback to the underlying document. If things aren't properly destroyed that will become a dangling listener.
Nekro Darkmoon
Nekro DarkmoonOP•12mo ago
Nekro Darkmoon
Nekro DarkmoonOP•12mo ago
Also for context this is how all this is being used to replace compendium sheets
TyphonJS (Michael)
TyphonJS (Michael)•12mo ago
And yeah.. I'll have to take a look at some of the additional Foundry integration points you've come up with and see about getting things into TRL proper to make life just a bit easier for everyone. If you get a chance though and can modify line 385 in node_modules\@typhonjs-fvtt\runtime\_dist\svelte\store\reducer\index.js from this.#indexUpdate(); to this.#indexUpdate(true); and let me know if that solves not manually having to do an index update that gives me some real world data to evaluate. Should be easy to do / make a production build then you can back it out, etc.
Nekro Darkmoon
Nekro DarkmoonOP•12mo ago
👌
Want results from more Discord servers?
Add your server