Conversation
| manager.current = new QueryModelManager(queryConfigs, searchParams, setSearchParams, modelLoader); | ||
| } | ||
|
|
||
| const state = useSyncExternalStore(manager.current.subscribe, manager.current.getSnapshot); |
There was a problem hiding this comment.
Very cool. Perfect usage of this.
| const state = useSyncExternalStore(manager.current.subscribe, manager.current.getSnapshot); | ||
|
|
||
| useEffect(() => { | ||
| // Note: It's not ideal because it will try to load selections for models that aren't active or aren't used in |
There was a problem hiding this comment.
Adding a
loadSelectionsattribute toQueryModel, dropping the flag from all actions
- This would address the issue outlined in thecomponentDidMountofwithQueryModels(Issue 48758), and allow us to stop automatically loading selections whenautoLoadis true.
- This may be the best time to make this change, since we can opt into that flag as needed while we transition usages ofwithQueryModelstouseQueryModels, which would net us the benefit of less API requests on each page.
- This could be done in a backwards compatible way, by keeping theloadSelectionsarg on allActionsmethods, but ignoring the arg (and emitting a warning when it is anything other than undefined).
I agree with making this change.
There was a problem hiding this comment.
Do you think we should take a backwards incompatible approach, and create a separate Actions interface for the hook that does not include the loadSelections flag? Or do you think we should keep using the existing Actions interface and emit warnings when the flag is used, but ignore it in favor of the QueryModel attribute.
| setFilters: (id: string, filters: Filter.IFilter[], loadSelections?: boolean) => void; | ||
| setMaxRows: (id: string, maxRows: number) => void; | ||
| setOffset: (id: string, offset: number, reloadModel?: boolean) => void; | ||
| setSchemaQuery: (id: string, schemaQuery: SchemaQuery, loadSelections?: boolean) => void; |
There was a problem hiding this comment.
Removing
Actions.setSchemaQuery
- While technically this is backwards incompatible we have zero usages of this method, and as far as I know, we have never had any usages of this method. I am not sure why it ever existed.
I agree we should remove this.
| ); | ||
| return new Set(result?.selected ?? []); | ||
| }, | ||
| async loadTotalCount(model: QueryModel, requestHandler: RequestHandler): Promise<number> { |
There was a problem hiding this comment.
Would introduction of useQueryModel() be a good time to also switch over to using selectRows() instead of selectRowsDeprecated? I'm thinking the hook could use selectRows and withQueryModels can continue using selectRowsDeprecated. Just a thought.
There was a problem hiding this comment.
I think it may be a good time for that change, but I haven't thought too hard about the implications. My only potential concern would be that we need to ensure that the underlying data in QueryModel is not shaped differently, and I don't think it would be. We could use this as an opportunity to improve the underlying type used on QueryModel (e.g. change get gridData's return type to Row[] instead of Record<string, any>[]. While techincally that would be a backwards incompatible change (because the type is so much more strict it could break builds) I'm already planning on bumping the major version in this PR so that would probably be fine.
| const manager = useRef<QueryModelManager>(null); | ||
|
|
||
| /* eslint-disable react-hooks/refs */ | ||
| if (!manager.current) { |
There was a problem hiding this comment.
Another approach that would be stable and have "built in" initialization is to use useState. Example:
export function useQueryModels(queryConfigs: QueryConfigMap, options: UseQueryModelsOptions = {}): InjectedQueryModels {
const { autoLoad = false, modelLoader } = options;
const [searchParams, setSearchParams] = useOptionalSearchParams();
const [manager] = useState(() => new QueryModelManager(queryConfigs, searchParams, setSearchParams, modelLoader));
const state = useSyncExternalStore(manager.subscribe, manager.getSnapshot);
useEffect(() => {
// Note: It's not ideal because it will try to load selections for models that aren't active or aren't used in
// grids (e.g., details models). We should add a loadSelections attribute to QueryModel so we can opt in to
// loading selections for our grid models only. See Issue 48758 for additional context.
if (autoLoad) manager.loadAllModels(true);
else manager.loadAllQueryInfos();
return () => {
manager.destroy();
};
}, []); // eslint-disable-line react-hooks/exhaustive-deps -- only run on mount
useEffect(() => {
manager.updateRouter(searchParams, setSearchParams);
}, [manager, searchParams, setSearchParams]);
return state;
}e45fc92 to
380dbe0
Compare
…s, add syncURL, as saveSettings, fix minor issues
Move network code from withQueryModels to DefaultQueryModelLoader
…adQueryInfo, loadAllQueryInfos useQueryModels: add options, wire up QueryModelLoader
… selectAllRows, selectPage, selectReport
…w, setFilters, setSchemaQuery, setSelections, setView
380dbe0 to
bd074e4
Compare
Rationale
This PR adds a
useQueryModelshook. Intended to be a replacement for thewithQueryModelsHOC. Note: the majority of the code was written directly by me, with some assistance from Claude (mostly by reviewing my code as I went to ensure it was at parity with the HOC, but several actions were implemented by Claude as well).Backwards incompatible changes I am considering making in this PR
loadSelectionsattribute toQueryModel, dropping the flag from all actionscomponentDidMountofwithQueryModels(Issue 48758), and allow us to stop automatically loading selections whenautoLoadis true.withQueryModelstouseQueryModels, which would net us the benefit of less API requests on each page.loadSelectionsarg on allActionsmethods, but ignoring the arg (and emitting a warning when it is anything other than undefined).Removing(done ✅ )Actions.setSchemaQueryNew feature(s) I am considering adding in this PR
reloadOnQueryConfigIdChangeswhich would cancel all pending API requests in the existing manager, then create a new manager with the most recent queryConfigs passed to the hook, if the IDs of any of the QueryConfig objects have changed.keyprop to force a remount of a component wrapped withwithQueryModelsObject.keys(queryConfigs).sort().join() !== Object.keys(queryModels).sort().join()Related Pull Requests
Changes
withQueryModels.tsxtoutils.tswithQueryModels.tsxtoQueryModel.tsRequestManagertoutils.tsQueryModelManageruseQueryModelshookQueryModelLoader: addloadTotalCountwithQueryModelsQueryModelLoader.loadTotalCountinitModelstoutils.tsbindURLtoutils.tsuseQueryModelsAPIKeysPanelsetSchemaQuery