leefsmp / Re-Flex

Resizable Flex layout container components for advanced React web applications
https://leefsmp.github.io/Re-Flex/index.html
MIT License
639 stars 72 forks source link

Bug: programmatically set `size` results in different `flexGrow` #147

Open akphi opened 3 years ago

akphi commented 3 years ago

Hi,

I programmatically set the size for a panel and have a button to toggle minimizing it. What I see is the size of the panel changes when I toggle the panel. See the videos below:

In this video, you can see Iconsole.log out the size and it stays the same at 300

https://user-images.githubusercontent.com/13574879/129611937-a6a414a8-50c2-4e22-b232-87ccc13dc13d.mov

In this video, I repeat the same experiment, but observe the flex in style, it changes

https://user-images.githubusercontent.com/13574879/129611880-3230e459-dd27-4003-af43-b2c64df03700.mov

akphi commented 3 years ago

@leefsmp Sorry, did you have a chance to take a look at this issue?

leefsmp commented 3 years ago

I don't have a suggestion from top of my head sorry. Do you have a codepen/sandbox that I could test quickly?

akphi commented 3 years ago

@leefsmp I will try to create a minimal repro in a few days!

akphi commented 3 years ago

@leefsmp Here's a small repro - https://codesandbox.io/s/wizardly-morse-47b2o You can click on the blue pad to toggle the size of the left panel and you would see it jumps

https://user-images.githubusercontent.com/13574879/134520595-b119df7c-8b8e-46b5-b732-b89cdacf9dd3.mov

akphi commented 2 years ago

@leefsmp did you have any chance looking at this issue?

leefsmp commented 2 years ago

I will try to look at it this week ...

mastercoms commented 2 years ago

I found this is a problem with ReflexContainer adjustFlex, for some reason the flex adjustment is different every time

Workaround: I set flex=1 for the visible component and flex=0 for the initially invisible sidebar.

akphi commented 2 years ago

@mastercoms thanks! I have tested it out and it does fix my problem

tachbana commented 2 years ago

I have the same issue. I am guessing that the reason for this problem is that the new size is calculated relative to the current size.

   newFlex = currentFlex * newSize / currentSize

So if the current size is very small, the error tends to be large.

I modified ReflexElement.js and ReflexContainer.js to not do relative calculations if prop.size changes. It seems to be working fine for now.

The specific changes are as follows.

ReflexElement.js

@@ -160,6 +160,7 @@
       /*#__PURE__*/
       _regenerator.default.mark(function _callee(prevProps, prevState, snapshot) {
         var directions, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, direction;
+        var _isSetPropSize;

         return _regenerator.default.wrap(function _callee$(_context) {
           while (1) {
@@ -167,7 +168,10 @@
               case 0:
                 if (!(prevState.size !== this.state.size)) {
                   _context.next = 28;
+                  _isSetPropSize = false;
                   break;
+                } else {
+                  _isSetPropSize = true;
                 }

                 directions = toArray(this.props.direction);
@@ -188,7 +192,8 @@
                 return this.props.events.emit('element.size', {
                   index: this.props.index,
                   size: this.props.size,
-                  direction: direction
+                  direction: direction,
+                  isSetPropSize: _isSetPropSize
                 });

               case 11:

ReflexContainer.js

@@ -150,7 +150,7 @@
           var splitterIdx = idx + dir;

           var availableOffset = _this.computeAvailableOffset(splitterIdx, dir * offset);
-
+          _this.state.isSetPropSize = data.isSetPropSize;
           _this.elements = null;

           if (availableOffset) {
@@ -168,6 +168,7 @@
           // TODO handle exception ...
           console.log(ex);
         }
+        delete _this.state.isSetPropSize;
       });
     });
     _this.events = new _ReflexEvents.default();
@@ -503,7 +504,7 @@
       var size = this.getSize(element);
       var idx = element.props.index;
       var newSize = Math.max(size + offset, 0);
-      var currentFlex = this.state.flexData[idx].flex;
+      var currentFlex = this.state.isSetPropSize ? 0 : this.state.flexData[idx].flex;
       var newFlex = currentFlex > 0 ? currentFlex * newSize / size : this.computePixelFlex() * newSize;
       this.state.flexData[idx].flex = !isFinite(newFlex) || isNaN(newFlex) ? 0 : newFlex;
     } /////////////////////////////////////////////////////////
leefsmp commented 2 years ago

could you submit a PR with modified code from the source in src/lib not the transpiled code.

LFdeWeb commented 1 year ago

I found this is a problem with ReflexContainer adjustFlex, for some reason the flex adjustment is different every time

Workaround: I set flex=1 for the visible component and flex=0 for the initially invisible sidebar.

sorry at this link https://github.com/leefsmp/Re-Flex/issues/147#issuecomment-925841151 , I can not fix it, by

          <ReflexElement  flex={0} size={size} direction={1}>
            <div className="App__side"></div>
          </ReflexElement>
          <ReflexSplitter />
          <ReflexElement flex={1} >
            <div className="App__panel"></div>
          </ReflexElement>
        </ReflexContainer> 

May I have a more complete code? please. @akphi @mastercoms