diff --git a/examples/position.js b/examples/position.js
new file mode 100644
index 0000000..fb170a3
--- /dev/null
+++ b/examples/position.js
@@ -0,0 +1,79 @@
+import React, { Component } from 'react';
+import Align from '../src';
+
+const align = {
+ points: ['cc', 'cc'],
+};
+
+class Demo extends Component {
+ state = {
+ left: 0,
+ top: 0,
+ };
+
+ eleRef = React.createRef();
+
+ render() {
+ const { left, top } = this.state;
+
+ return (
+
+
+
+
this.eleRef.current}
+ align={align}
+ keepingAlign
+ >
+
+ Align
+
+
+
+
+
+ );
+ }
+}
+
+export default Demo;
diff --git a/src/Align.tsx b/src/Align.tsx
index ce6b1ac..7433ffc 100644
--- a/src/Align.tsx
+++ b/src/Align.tsx
@@ -22,6 +22,8 @@ export interface AlignProps {
monitorWindowResize?: boolean;
disabled?: boolean;
children: React.ReactElement;
+ /** Always trigger align with each render */
+ keepAlign?: boolean;
}
interface MonitorRef {
@@ -43,11 +45,27 @@ function getPoint(point: TargetType) {
return point;
}
+interface InternalTestProps {
+ INTERNAL_TRIGGER_ALIGN?: Function;
+}
+
const Align: React.RefForwardingComponent = (
- { children, disabled, target, align, onAlign, monitorWindowResize, monitorBufferTime = 0 },
+ {
+ children,
+ disabled,
+ target,
+ align,
+ onAlign,
+ monitorWindowResize,
+ monitorBufferTime = 0,
+ keepAlign,
+ ...restProps
+ },
ref,
) => {
- const cacheRef = React.useRef<{ element?: HTMLElement; point?: TargetPoint }>({});
+ const cacheRef = React.useRef<{ element?: HTMLElement; point?: TargetPoint }>(
+ {},
+ );
const nodeRef = React.useRef();
let childNode = React.Children.only(children);
@@ -63,7 +81,17 @@ const Align: React.RefForwardingComponent = (
forceAlignPropsRef.current.onAlign = onAlign;
const [forceAlign, cancelForceAlign] = useBuffer(() => {
- const { disabled: latestDisabled, target: latestTarget } = forceAlignPropsRef.current;
+ if (
+ process.env.NODE_ENV !== 'production' &&
+ (restProps as InternalTestProps).INTERNAL_TRIGGER_ALIGN
+ ) {
+ (restProps as InternalTestProps).INTERNAL_TRIGGER_ALIGN();
+ }
+
+ const {
+ disabled: latestDisabled,
+ target: latestTarget,
+ } = forceAlignPropsRef.current;
if (!latestDisabled && latestTarget) {
const source = nodeRef.current;
@@ -112,10 +140,16 @@ const Align: React.RefForwardingComponent = (
if (nodeRef.current !== sourceResizeMonitor.current.element) {
sourceResizeMonitor.current.cancel();
sourceResizeMonitor.current.element = nodeRef.current;
- sourceResizeMonitor.current.cancel = monitorResize(nodeRef.current, forceAlign);
+ sourceResizeMonitor.current.cancel = monitorResize(
+ nodeRef.current,
+ forceAlign,
+ );
}
- if (cacheRef.current.element !== element || !isSamePoint(cacheRef.current.point, point)) {
+ if (
+ cacheRef.current.element !== element ||
+ !isSamePoint(cacheRef.current.point, point)
+ ) {
forceAlign();
// Add resize observer
@@ -136,6 +170,15 @@ const Align: React.RefForwardingComponent = (
}
}, [disabled]);
+ /**
+ * [Legacy] Should keep re-algin since we don't know if target position changed.
+ */
+ React.useEffect(() => {
+ if (keepAlign && !disabled) {
+ forceAlign(true);
+ }
+ });
+
// Listen for window resize
const winResizeRef = React.useRef<{ remove: Function }>(null);
React.useEffect(() => {
diff --git a/tests/element.test.js b/tests/element.test.js
index 42d2344..b747632 100644
--- a/tests/element.test.js
+++ b/tests/element.test.js
@@ -26,7 +26,10 @@ describe('element align', () => {
render() {
return (
-
+
target
@@ -73,12 +76,33 @@ describe('element align', () => {
it('disabled should trigger align', () => {
const onAlign = jest.fn();
- const wrapper = mount();
+ const wrapper = mount(
+ ,
+ );
expect(onAlign).not.toHaveBeenCalled();
wrapper.setProps({ disabled: false });
jest.runAllTimers();
expect(onAlign).toHaveBeenCalled();
});
+
+ it('keepAlign', () => {
+ const triggerAlign = jest.fn();
+
+ class TestAlign extends React.Component {
+ state = {};
+
+ render = () => ;
+ }
+
+ const wrapper = mount();
+ const times = triggerAlign.mock.calls.length;
+
+ for (let i = 0; i < 10; i += 1) {
+ wrapper.instance().forceUpdate();
+ }
+
+ expect(triggerAlign.mock.calls.length > times).toBeTruthy();
+ });
});
/* eslint-enable */