mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[IMP] hooks: introduce useEffect
Co-Authored-By: Samuel Degueldre <sad@odoo.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import type { Env } from "./app/app";
|
||||
import { getCurrent } from "./component/component_node";
|
||||
import { onMounted, onPatched, onWillPatch, onWillUnmount } from "./component/lifecycle_hooks";
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// useRef
|
||||
@@ -39,3 +40,53 @@ export function useSubEnv(envExtension: Env) {
|
||||
const node = getCurrent()!;
|
||||
node.childEnv = Object.freeze(Object.assign({}, node.childEnv, envExtension));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// useEffect
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const NO_OP = () => {};
|
||||
/**
|
||||
* @param {...any} dependencies the dependencies computed by computeDependencies
|
||||
* @returns {void|(()=>void)} a cleanup function that reverses the side
|
||||
* effects of the effect callback.
|
||||
*/
|
||||
type Effect = (...dependencies: any[]) => void | (() => void);
|
||||
|
||||
/**
|
||||
* This hook will run a callback when a component is mounted and patched, and
|
||||
* will run a cleanup function before patching and before unmounting the
|
||||
* the component.
|
||||
*
|
||||
* @param {Effect} effect the effect to run on component mount and/or patch
|
||||
* @param {()=>any[]} [computeDependencies=()=>[NaN]] a callback to compute
|
||||
* dependencies that will decide if the effect needs to be cleaned up and
|
||||
* run again. If the dependencies did not change, the effect will not run
|
||||
* again. The default value returns an array containing only NaN because
|
||||
* NaN !== NaN, which will cause the effect to rerun on every patch.
|
||||
*/
|
||||
export function useEffect(effect: Effect, computeDependencies: () => any[] = () => [NaN]) {
|
||||
let cleanup: () => void;
|
||||
let dependencies: any[];
|
||||
onMounted(() => {
|
||||
dependencies = computeDependencies();
|
||||
cleanup = effect(...dependencies) || NO_OP;
|
||||
});
|
||||
|
||||
let shouldReapplyOnPatch = false;
|
||||
onWillPatch(() => {
|
||||
const newDeps = computeDependencies();
|
||||
shouldReapplyOnPatch = newDeps.some((val, i) => val !== dependencies[i]);
|
||||
if (shouldReapplyOnPatch) {
|
||||
cleanup();
|
||||
dependencies = newDeps;
|
||||
}
|
||||
});
|
||||
onPatched(() => {
|
||||
if (shouldReapplyOnPatch) {
|
||||
cleanup = effect(...dependencies) || NO_OP;
|
||||
}
|
||||
});
|
||||
|
||||
onWillUnmount(() => cleanup());
|
||||
}
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ export { Portal } from "./misc/portal";
|
||||
export { Memo } from "./misc/memo";
|
||||
export { css, xml } from "./tags";
|
||||
export { useState } from "./reactivity";
|
||||
export { useRef, useEnv, useSubEnv } from "./hooks";
|
||||
export { useRef, useEnv, useSubEnv, useEffect } from "./hooks";
|
||||
export const utils = { EventBus, whenReady, loadFile };
|
||||
|
||||
export {
|
||||
|
||||
Reference in New Issue
Block a user