Eliav2 / react-xarrows

Draw arrows (or lines) between components in React!
https://codesandbox.io/embed/github/Eliav2/react-xarrows/tree/master/examples?fontsize=14&hidenavigation=1&theme=dark
MIT License
584 stars 75 forks source link

Add support for force updates on xarrows #169

Open fentech opened 1 year ago

fentech commented 1 year ago

Hi! 👋

Firstly, thanks for your work on this project! 🙂

Today I used patch-package to patch react-xarrows@2.0.2 for the project I'm working on.

I was seeing an issue with arrows not updating when new elements were added or removed from the DOM, and it was also ignoring manual updateXarrow calls, so I added an override to manually trigger an update to arrow positions when the useXarrow hook is used.

Here is the diff that solved my problem:

diff --git a/node_modules/react-xarrows/lib/index.js b/node_modules/react-xarrows/lib/index.js
index 101bd9e..f55878e 100644
--- a/node_modules/react-xarrows/lib/index.js
+++ b/node_modules/react-xarrows/lib/index.js
@@ -109,6 +109,7 @@ var Xwrapper_1 = __webpack_require__(/*! ../Xwrapper */ "./src/Xwrapper.tsx");
 var propTypes_1 = __importDefault(__webpack_require__(/*! ./propTypes */ "./src/Xarrow/propTypes.ts"));
 var GetPosition_1 = __webpack_require__(/*! ./utils/GetPosition */ "./src/Xarrow/utils/GetPosition.tsx");
 var log = console.log;
+
 var Xarrow = function (props) {
     // log('xarrow update');
     var _a;
@@ -122,7 +123,7 @@ var Xarrow = function (props) {
         headOpacityAnimRef: react_1.useRef(null),
     });
     var _b = mainRef.current, svgRef = _b.svgRef, lineRef = _b.lineRef, headRef = _b.headRef, tailRef = _b.tailRef, lineDrawAnimRef = _b.lineDrawAnimRef, lineDashAnimRef = _b.lineDashAnimRef, headOpacityAnimRef = _b.headOpacityAnimRef;
-    react_1.useContext(Xwrapper_1.XarrowContext);
+    const {forcedRenderCount} = react_1.useContext(Xwrapper_1.XarrowContext);
     var xProps = useXarrowProps_1.default(props, mainRef.current);
     var propsRefs = xProps[0];
     var labels = propsRefs.labels, lineColor = propsRefs.lineColor, headColor = propsRefs.headColor, tailColor = propsRefs.tailColor, strokeWidth = propsRefs.strokeWidth, showHead = propsRefs.showHead, showTail = propsRefs.showTail, dashness = propsRefs.dashness, headShape = propsRefs.headShape, tailShape = propsRefs.tailShape, showXarrow = propsRefs.showXarrow, animateDrawing = propsRefs.animateDrawing, zIndex = propsRefs.zIndex, passProps = propsRefs.passProps, arrowBodyProps = propsRefs.arrowBodyProps, arrowHeadProps = propsRefs.arrowHeadProps, arrowTailProps = propsRefs.arrowTailProps, SVGcanvasProps = propsRefs.SVGcanvasProps, divContainerProps = propsRefs.divContainerProps, divContainerStyle = propsRefs.divContainerStyle, SVGcanvasStyle = propsRefs.SVGcanvasStyle, _debug = propsRefs._debug, shouldUpdatePosition = propsRefs.shouldUpdatePosition;
@@ -183,6 +184,9 @@ var Xarrow = function (props) {
             shouldUpdatePosition.current = false;
         }
     });
+    react_1.useEffect(function () {
+        shouldUpdatePosition.current = true
+    }, [forcedRenderCount])
     // log('st', st);
     var xOffsetHead = st.x2 - st.arrowHeadOffset.x;
     var yOffsetHead = st.y2 - st.arrowHeadOffset.y;
@@ -1273,14 +1277,18 @@ var updateRefCount = 0;
 var log = console.log;
 var XarrowProvider = function (_a) {
     var children = _a.children, instanceCount = _a.instanceCount;
-    var _b = react_1.useState({}), setRender = _b[1];
-    var updateXarrow = function () { return setRender({}); };
+    var _b = react_1.useState(0), renderCount = _b[0], setRender = _b[1];
+    var _c = react_1.useState(0), forcedRenderCount = _c[0], setForcedRender = _c[1];
+    var updateXarrow = function (forced = false) {
+        if (forced) setForcedRender(prev => prev + 1)
+        setRender(prev => prev + 1);
+    };
     react_1.useEffect(function () {
         instanceCount.current = updateRefCount; // so this instance would know what is id
         updateRef[instanceCount.current] = updateXarrow;
     }, []);
     // log('XarrowProvider', updateRefCount);
-    return react_1.default.createElement(exports.XarrowContext.Provider, { value: updateXarrow }, children);
+    return react_1.default.createElement(exports.XarrowContext.Provider, { value: { updateXarrow, renderCount, forcedRenderCount } }, children);
 };
 var XelemProvider = function (_a) {
     var children = _a.children, instanceCount = _a.instanceCount;
@@ -1396,8 +1404,8 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
 var react_1 = __webpack_require__(/*! react */ "react");
 var Xwrapper_1 = __webpack_require__(/*! ./Xwrapper */ "./src/Xwrapper.tsx");
 var useXarrow = function () {
-    var _a = react_1.useState({}), setRender = _a[1];
-    var reRender = function () { return setRender({}); };
+    // var _a = react_1.useState(0), setRender = _a[1];
+    // var reRender = function () { return setRender(prev => prev + 1); };
     var updateXarrow = react_1.useContext(Xwrapper_1.XelemContext);
     if (!updateXarrow)
         updateXarrow = function () { };
@@ -1407,7 +1415,7 @@ var useXarrow = function () {
     react_1.useLayoutEffect(function () {
         updateXarrow();
     });
-    return reRender;
+    return function () { return updateXarrow(true) };
 };
 exports.default = useXarrow;

This issue body was partially generated by patch-package.

fentech commented 1 year ago

Need to make some changes the above

fentech commented 1 year ago

I updated the description details