Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Watermark container size changes, resulting in incomplete display or disappearance of watermarks #48660

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
9 changes: 7 additions & 2 deletions components/watermark/index.tsx
Expand Up @@ -116,7 +116,8 @@

// Used for nest case like Modal, Drawer
const [subElements, setSubElements] = React.useState(new Set<HTMLElement>());

// Used for re-rendering the watermark Container
const [containerKey, setContainerKey] = React.useState(new Date().getTime());
// Nest elements should also support watermark
const targetElements = React.useMemo(() => {
const list = container ? [container] : [];
Expand Down Expand Up @@ -207,7 +208,8 @@

// ============================= Effect =============================
// Append watermark to the container
const [appendWatermark, removeWatermark, isWatermarkEle] = useWatermark(markStyle);
const [appendWatermark, removeWatermark, isWatermarkEle, isWatermarkContainer] =
useWatermark(markStyle);

useEffect(() => {
if (watermarkInfo) {
Expand All @@ -222,6 +224,8 @@
mutations.forEach((mutation) => {
if (reRendering(mutation, isWatermarkEle)) {
syncWatermark();
} else if (reRendering(mutation, isWatermarkContainer)) {
setContainerKey(containerKey + 1);

Check warning on line 228 in components/watermark/index.tsx

View check run for this annotation

Codecov / codecov/patch

components/watermark/index.tsx#L228

Added line #L228 was not covered by tests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感觉搞复杂了,如果只是需要更新视图的话,直接用 forceUpdate 就可以了吧:

import useForceUpdate from '../_util/hooks/useForceUpdate';

const forceUpdate = useForceUpdate();

if (xxxx) {
  forceUpdate();
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

用时间戳做 key 的初始值感觉不是很好的解法,初始值还不如直接写 0 好了,另外 new Date().getTime() 可以简写为 Date.now()

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我曾经尝试过使用useForceUpdate(useReducer)方法来触发视图更新,但是没有解决这个问题

但是我采用了您key初始值为0的建议

**解决思路:**父元素旧的dom替换成新的dom,如果不换成新的dom浏览器控制台设置的属性将不会消失(如果您有更好的解决思路可以提出)

**解决方案:**将父元素div的key进行更新,react的diff算法检测到前后key不一致,会调用ReactElement方法来生成新的fiberNode,最终产生一个新的真实dom

为什么useReducer方法无法解决这个问题
useReducer只是触发视图的更新,父元素的key或type没有发生改变,react会复用这个老的真实dom,导致浏览器控制台设置的CSS属性依旧存在

}
});
};
Expand Down Expand Up @@ -280,6 +284,7 @@

return (
<div
key={containerKey}
ref={setContainer}
className={classNames(className, rootClassName)}
style={{ position: 'relative', ...style }}
Expand Down
5 changes: 4 additions & 1 deletion components/watermark/useWatermark.ts
Expand Up @@ -26,6 +26,7 @@ export default function useWatermark(
appendWatermark: AppendWatermark,
removeWatermark: (container: HTMLElement) => void,
isWatermarkEle: (ele: Node) => boolean,
isWatermarkContainer: (ele: Node) => boolean,
] {
const [watermarkMap] = React.useState(() => new Map<HTMLElement, HTMLDivElement>());

Expand Down Expand Up @@ -70,5 +71,7 @@ export default function useWatermark(

const isWatermarkEle = (ele: any) => Array.from(watermarkMap.values()).includes(ele);

return [appendWatermark, removeWatermark, isWatermarkEle];
const isWatermarkContainer = (ele: any) => Array.from(watermarkMap.keys()).includes(ele);

return [appendWatermark, removeWatermark, isWatermarkEle, isWatermarkContainer];
}