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

Removing multiple panes during a rerender causes a runtime error #314

Closed
Gelio opened this issue May 31, 2022 · 4 comments · Fixed by #320
Closed

Removing multiple panes during a rerender causes a runtime error #314

Gelio opened this issue May 31, 2022 · 4 comments · Fixed by #320
Assignees
Labels
bug Something isn't working

Comments

@Gelio
Copy link
Contributor

Gelio commented May 31, 2022

Hey! Thanks for a great library, it's a pleasure to use!

I encountered a runtime exception when I removed multiple panes during a single rerender:

image

Analysis

I believe the problematic piece of code is this loop that calls removeView for each removed pane:

allotment/src/allotment.tsx

Lines 297 to 303 in cd38c27

exit.forEach((flag, index) => {
if (flag) {
splitViewRef.current?.removeView(index);
panes.splice(index, 1);
views.current.splice(index, 1);
}
});

I believe the problem is with the order of removal. If we have 3 panes (indices [0, 1, 2]) and remove panes with indices 1 and 2 during a single render, then this loop calls removeView(1) and then removeView(2). The second call fails because after the first removeView(1) there are only 2 panes (with indices [0, 1]). If the order of operations was reversed and we removed panes from last to first, we would call removeView(2) first and then removeView(1), which would work as expected.

Workarouund

The workaround that I came up with is to remove one pane at a time in a very quick succession to give those useEffects time to refresh the indices.

Instead of just

const onClick = () => {
  setExtraPanesCount(0);
};

I now use:

const onClick = () => {
  const removePane = () => {
    setExtraPanesCount((panes) => {
      if (panes > 1) {
        setTimeout(removePane, 0);
      }
      return panes - 1;
    });
  };

  removePane();
};

which works well.

it would be ideal if I could remove all the panes at once but that requires fixing this bug.

@johnwalley johnwalley self-assigned this Jun 1, 2022
@johnwalley johnwalley added the bug Something isn't working label Jun 1, 2022
@johnwalley
Copy link
Owner

Hi @Gelio, thanks for the detailed issue.

I'll prioritise getting this fixed as throwing an exception for a normal piece of functionality isn't great. I'll ping you when the release with the fix goes out.

@Gelio
Copy link
Contributor Author

Gelio commented Jun 1, 2022

Thanks for a quick response! Don't worry about it too much, the workaround I described works well enough that it is a minor nuisance for me now. Take your time 🙂

@johnwalley johnwalley linked a pull request Jun 5, 2022 that will close this issue
@johnwalley
Copy link
Owner

I've created a PR (#320) with a fix 🙂. I also have a PR (#321) I'm working on which adds end-to-end tests which should help catch this type of error in the future.

I'll get them merged and published sometime this week.

@Gelio
Copy link
Contributor Author

Gelio commented Jun 6, 2022

Thanks for the effort, I appreciate that you came up with a fix so soon 👍 I'm looking forward to having the fix released, but there's no rush, so take your time

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants