Graphite: Run onChange/onRunQuery after reducer action finishes (#42136) (#42224)

(cherry picked from commit b3e417f768)

Co-authored-by: Piotr Jamróz <pm.jamroz@gmail.com>
This commit is contained in:
Grot (@grafanabot) 2021-11-24 08:37:24 -05:00 committed by GitHub
parent dfdb745e36
commit 01a53c349a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 24 additions and 8 deletions

View File

@ -31,6 +31,7 @@ export const GraphiteQueryEditorContext = ({
children, children,
}: PropsWithChildren<GraphiteQueryEditorProps>) => { }: PropsWithChildren<GraphiteQueryEditorProps>) => {
const [state, setState] = useState<GraphiteQueryEditorState>(); const [state, setState] = useState<GraphiteQueryEditorState>();
const [needsRefresh, setNeedsRefresh] = useState<boolean>(false);
const dispatch = useMemo(() => { const dispatch = useMemo(() => {
return createStore((state) => { return createStore((state) => {
@ -68,6 +69,19 @@ export const GraphiteQueryEditorContext = ({
[dispatch, query] [dispatch, query]
); );
useEffect(
() => {
if (needsRefresh && state) {
setNeedsRefresh(false);
onChange({ ...query, target: state.target.target });
onRunQuery();
}
},
// adding state to dependencies causes infinite loops
// eslint-disable-next-line react-hooks/exhaustive-deps
[needsRefresh, onChange, onRunQuery, query]
);
if (!state) { if (!state) {
dispatch( dispatch(
actions.init({ actions.init({
@ -78,9 +92,10 @@ export const GraphiteQueryEditorContext = ({
// list of queries is passed only when the editor is in Dashboards. This is to allow interpolation // list of queries is passed only when the editor is in Dashboards. This is to allow interpolation
// of sub-queries which are stored in "targetFull" property used by alerting in the backend. // of sub-queries which are stored in "targetFull" property used by alerting in the backend.
queries: queries || [], queries: queries || [],
refresh: (target: string) => { refresh: () => {
onChange({ ...query, target: target }); // do not run onChange/onRunQuery straight away to ensure the internal state gets updated first
onRunQuery(); // to avoid race conditions (onChange could update props before the reducer action finishes)
setNeedsRefresh(true);
}, },
}) })
); );

View File

@ -161,7 +161,7 @@ export function handleTargetChanged(state: GraphiteQueryEditorState): void {
); );
if (state.queryModel.target.target !== oldTarget && !state.paused) { if (state.queryModel.target.target !== oldTarget && !state.paused) {
state.refresh(state.target.target); state.refresh();
} }
} }

View File

@ -25,7 +25,7 @@ export type GraphiteQueryEditorState = {
// external dependencies // external dependencies
datasource: GraphiteDatasource; datasource: GraphiteDatasource;
target: GraphiteTarget; target: GraphiteTarget;
refresh: (target: string) => void; refresh: () => void;
queries?: DataQuery[]; queries?: DataQuery[];
templateSrv: TemplateSrv; templateSrv: TemplateSrv;
range?: TimeRange; range?: TimeRange;
@ -134,7 +134,7 @@ const reducer = async (action: Action, state: GraphiteQueryEditorState): Promise
} }
if (actions.unpause.match(action)) { if (actions.unpause.match(action)) {
state.paused = false; state.paused = false;
state.refresh(state.target.target); state.refresh();
} }
if (actions.addFunction.match(action)) { if (actions.addFunction.match(action)) {
const newFunc = state.datasource.createFuncInstance(action.payload.name, { const newFunc = state.datasource.createFuncInstance(action.payload.name, {
@ -175,7 +175,7 @@ const reducer = async (action: Action, state: GraphiteQueryEditorState): Promise
handleTargetChanged(state); handleTargetChanged(state);
} }
if (actions.runQuery.match(action)) { if (actions.runQuery.match(action)) {
state.refresh(state.target.target); state.refresh();
} }
if (actions.toggleEditorMode.match(action)) { if (actions.toggleEditorMode.match(action)) {
state.target.textEditor = !state.target.textEditor; state.target.textEditor = !state.target.textEditor;

View File

@ -77,5 +77,6 @@ export type GraphiteQueryEditorDependencies = {
range?: TimeRange; range?: TimeRange;
templateSrv: TemplateSrv; templateSrv: TemplateSrv;
queries: DataQuery[]; queries: DataQuery[];
refresh: (target: string) => void; // schedule onChange/onRunQuery after the reducer actions finishes
refresh: () => void;
}; };