mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-12 23:04:52 +09:00
Every view page handled a resource that can't be shown its own way, and users without the subscribe permission were left on a spinner forever. Adds useResourceState and a ResourceState component, used by the host, instance, mod pack, icon reference, user, role and plugin pages and exported for plugin pages. The single item hooks now also return the subscription error. Resolves #1165
37 lines
1.3 KiB
TypeScript
37 lines
1.3 KiB
TypeScript
import { useCallback, useContext, useEffect, useState, useSyncExternalStore } from "react";
|
|
import { Static } from "@sinclair/typebox";
|
|
import { Config, InstanceConfigGetRequest } from "@clusterio/lib";
|
|
import ControlContext from "../components/ControlContext";
|
|
|
|
export function useInstance(id?: number) {
|
|
const [instances, synced, error] = useInstances();
|
|
return [id !== undefined ? instances.get(id) : undefined, synced, error] as const;
|
|
}
|
|
|
|
export function useInstances() {
|
|
const control = useContext(ControlContext);
|
|
const subscribe = useCallback((callback: () => void) => control.instances.subscribe(callback), [control]);
|
|
return useSyncExternalStore(subscribe, () => control.instances.getSnapshot());
|
|
}
|
|
|
|
export function useInstanceConfig(id?: number) {
|
|
let control = useContext(ControlContext);
|
|
const [config, setConfig] = useState(undefined as undefined | Static<typeof Config.jsonSchema>);
|
|
|
|
useEffect(() => {
|
|
setConfig(undefined);
|
|
if (id === undefined) {
|
|
return undefined;
|
|
}
|
|
|
|
// Responses for a previous id must not overwrite the current one.
|
|
let current = true;
|
|
control.send(new InstanceConfigGetRequest(id))
|
|
.then(conf => { if (current) { setConfig(conf); } })
|
|
.catch(() => {}); // Config is optional, the caller falls back to not having it
|
|
return () => { current = false; };
|
|
}, [id]);
|
|
|
|
return config;
|
|
};
|