diff --git a/ivette/.eslintrc.js b/ivette/.eslintrc.js
index 32bd12c19a23afe635ae2dc5b4edc8f88b196c85..00bfecaef72a80a2857f7d7042c24c42e7baa8a9 100644
--- a/ivette/.eslintrc.js
+++ b/ivette/.eslintrc.js
@@ -17,6 +17,8 @@ module.exports = {
   },
   rules: {
     "react/display-name": "off",
+    // Be more strict on usage of useMemo and useRef
+    "react-hooks/exhaustive-deps": "error",
     // Allow type any, even if it should be avoided
     "@typescript-eslint/no-explicit-any": "off",
     // Allow functions without return type, even if exported function should have one
diff --git a/ivette/src/frama-c/states.ts b/ivette/src/frama-c/states.ts
index c00809c195bba44f12fa413fdeb2cffba8ac44b3..f822f19f1e3596b9fe42f524db6e5c59ba766527 100644
--- a/ivette/src/frama-c/states.ts
+++ b/ivette/src/frama-c/states.ts
@@ -158,40 +158,42 @@ export function useState(id: string) {
  *  in case of errors, but will keep the last received value until a new one is
  *  actually received.
  */
-export function useRequest(rq: string, params: any, options: any = {}) {
+export function useRequest(
+  rq: string,
+  params: any,
+  options: any = {},
+) {
+  const state = React.useRef<string>();
   const project = useProject();
-  const [value, setValue] = React.useState(options.offline);
+  const [response, setResponse] = React.useState(options.offline);
+  const footprint =
+    project ? JSON.stringify([project, rq, params]) : undefined;
 
-  React.useEffect(() => {
+  async function trigger() {
     if (project) {
-      const pending = options.prending;
-      if (pending !== null) {
-        setValue(pending);
+      try {
+        const r = await Server.GET({ endpoint: rq, params });
+        setResponse(r);
+      } catch (errmsg) {
+        if (Dome.DEVEL)
+          console.warn(`[Server] use request '${rq}':`, errmsg);
+        const err = options.error;
+        if (err !== undefined) setResponse(err);
       }
-      (async () => {
-        try {
-          const sr: Server.Request = { endpoint: rq, params };
-          const v = await Server.GET(sr);
-          setValue(v);
-        } catch (err) {
-          if (Dome.DEVEL) {
-            console.warn(`[Server] use request '${rq}':`, err);
-          }
-          const { error } = options;
-          if (error !== null) {
-            setValue(error);
-          }
-        }
-      })();
     } else {
-      const v = options.offline;
-      if (value !== v) {
-        setValue(v);
-      }
+      const off = options.offline;
+      if (off !== undefined) setResponse(off);
     }
-  }, [project, rq, JSON.stringify(params)]);
+  }
+
+  React.useEffect(() => {
+    if (state.current !== footprint) {
+      state.current = footprint;
+      trigger();
+    }
+  });
 
-  return value;
+  return response;
 }
 
 // --------------------------------------------------------------------------
@@ -243,7 +245,7 @@ export function useDictionary(
       if (k && (!filter || filter(tg))) d[k] = tg;
     });
     return d;
-  }, [tags, filter]);
+  }, [key, tags, filter]);
   return dict;
 }
 
diff --git a/ivette/src/renderer/ASTview.tsx b/ivette/src/renderer/ASTview.tsx
index d7b941609926144dd3ba8cf0cce9045310c54d23..78c071618b827b2b70fe1f4b9d7cb3b51ec9be76 100644
--- a/ivette/src/renderer/ASTview.tsx
+++ b/ivette/src/renderer/ASTview.tsx
@@ -18,13 +18,13 @@ import 'codemirror/theme/ambiance.css';
 // --- Rich Text Printer
 // --------------------------------------------------------------------------
 
-const print = (buffer: any, text: string) => {
+const printAST = (buffer: any, text: string) => {
   if (Array.isArray(text)) {
     const tag = text.shift();
     if (tag !== '') {
       buffer.openTextMarker({ id: tag });
     }
-    text.forEach((txt) => print(buffer, txt));
+    text.forEach((txt) => printAST(buffer, txt));
     if (tag !== '') {
       buffer.closeTextMarker();
     }
@@ -33,45 +33,51 @@ const print = (buffer: any, text: string) => {
   }
 };
 
+async function loadAST(buffer: any, theFunction?: string, theMarker?: string) {
+  buffer.clear();
+  if (theFunction) {
+    buffer.log('// Loading', theFunction, '…');
+    (async () => {
+      const data = await Server.GET({
+        endpoint: 'kernel.ast.printFunction',
+        params: theFunction,
+      });
+      buffer.clear();
+      if (!data)
+        buffer.log('// No code for function ', theFunction);
+      printAST(buffer, data);
+      if (theMarker)
+        buffer.scroll(theMarker, undefined);
+      return;
+    })();
+  }
+}
+
 // --------------------------------------------------------------------------
 // --- AST Printer
 // --------------------------------------------------------------------------
 
 const ASTview = () => {
+
   // Hooks
   const buffer = React.useMemo(() => new RichTextBuffer(), []);
+  const printed = React.useRef();
   const [select, setSelect] = States.useSelection();
   const theFunction = select && select.function;
   const theMarker = select && select.marker;
 
   // Hook: async loading
   React.useEffect(() => {
-    buffer.clear();
-    if (theFunction) {
-      buffer.log('// Loading', theFunction, '…');
-      (async () => {
-        const sr: Server.Request = {
-          endpoint: 'kernel.ast.printFunction',
-          params: theFunction,
-        };
-        const data = await Server.GET(sr);
-        buffer.clear();
-        if (!data) {
-          buffer.log('// No code for function ', theFunction);
-        }
-        print(buffer, data);
-        if (theMarker) {
-          buffer.scroll(theMarker, undefined);
-        }
-        return;
-      })();
+    if (printed.current !== theFunction) {
+      printed.current = theFunction;
+      loadAST(buffer, theFunction, theMarker);
     }
-  }, [theFunction]);
+  });
 
-  // Hook: scrolling
+  // Hook: marker scrolling
   React.useEffect(() => {
     if (theMarker) buffer.scroll(theMarker, undefined);
-  }, [theMarker]);
+  }, [buffer, theMarker]);
 
   // Callbacks
   const onSelection = (marker: any) => setSelect({ marker });
@@ -89,6 +95,7 @@ const ASTview = () => {
       />
     </Vfill>
   );
+
 };
 
 // --------------------------------------------------------------------------