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

fix(panel): append panel body as a child element #3561

Merged
merged 6 commits into from
Mar 12, 2019

Conversation

francoischalifour
Copy link
Member

@francoischalifour francoischalifour commented Mar 1, 2019

Summary

There's an issue where Preact loses the bodyRef ref when the widget re-renders because it cleans the tree. This issue exists with both preact and preact-compat (version < 10.0.0) but not with react (tested by @samouss).

This problem makes the collapsible option impossible to implement in the panel. It also causes other issues:

The input range width loses the reference of its container.

Result

This solution doesn't rely on refs but on plain DOM manipulation. It inserts the body when the Preact component is mounted.

Note that this solution inserts another div inside div.ais-Panel-body (this is a recurring issue encountered in the GeoSearch component for example without big consequences).

@francoischalifour francoischalifour requested a review from a team March 1, 2019 11:22
@@ -21,37 +21,40 @@ storiesOf('Panel', module)
})
)
.add(
'with ratingMenu',
'with range input',
Copy link
Member Author

Choose a reason for hiding this comment

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

I updated these stories because they conflicted with the playground.

@algobot
Copy link
Contributor

algobot commented Mar 1, 2019

Deploy preview for instantsearchjs ready!

Built with commit e6057c3

https://deploy-preview-3561--instantsearchjs.netlify.com

Copy link
Contributor

@samouss samouss left a comment

Choose a reason for hiding this comment

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

We could add a test about the actual issue, the fact that the widget was unmount/mount at each render.

@Haroenv
Copy link
Contributor

Haroenv commented Mar 1, 2019

As expected, this added an extra div between the body and the widget root. I think it's a reasonable tradeoff in this case, although I wonder if there might be another way

@francoischalifour
Copy link
Member Author

@samouss Any clue what would be a good way to test this? It seems to be very specific to Preact, and especially this current version. I'm not sure it would make sense to test that since the test can break if we upgrade the Preact dependency someday.

(I added a test on the lifecycle but it's unrelated)

@Haroenv We could mount the widget in a DocumentFragment and insert this fragment into the panel body div. However, InstantSearch.js doesn't seem to be compatible with DocumentFragments as containers (it doesn't render anything).

@samouss
Copy link
Contributor

samouss commented Mar 1, 2019

@francoischalifour I don't think it's an issue, it might be an expected behaviour. Indeed it's very specific to Preact like the issue we have. IMO it worth cover it with a test to avoid any regression in the future. We can reproduce the exact same logic that we have inside the Panel and test that the component is not re-created.

@francoischalifour
Copy link
Member Author

FYI we decided not to test #3561 (comment). This will be fixed by Preact X.

@@ -112,18 +111,19 @@ export default function panel({

const renderPanel = renderer({
Copy link
Contributor

@samouss samouss Mar 6, 2019

Choose a reason for hiding this comment

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

We can remove the indirection created by the renderer. We can avoid to return a new function from the renderer and provide the full list of argument each time call the function. We do this in widgets because we don't have the control on the render call (which can be avoided anyway). Here we do have the control (see below). We can do it in another PR.

const renderer = ({
  containerNode,
  bodyContainerNode,
  cssClasses,
  templateProps,
  options,
  hidden
}) => {
  render(
    <Panel
      cssClasses={cssClasses}
      hidden={hidden}
      templateProps={templateProps}
      data={options}
      bodyElement={bodyContainerNode}
    />,
    containerNode
  );
};

@francoischalifour francoischalifour merged commit 3de59a3 into develop Mar 12, 2019
@francoischalifour francoischalifour deleted the fix/panel-body branch March 12, 2019 11:10
francoischalifour added a commit that referenced this pull request Mar 18, 2019
## [3.2.1](v3.1.0...v3.2.1) (2019-03-18)

### Bug Fixes

* **connectToggleRefinement:** keep user provided, but falsy values ([#3526](#3526)) ([958a151](958a151))
* **instantsearch:** update usage errors ([#3543](#3543)) ([a2a800b](a2a800b))
* **panel:** append panel body as a child element ([#3561](#3561)) ([3de59a3](3de59a3))
* **poweredBy:** remove TypeScript extension in import ([#3530](#3530)) ([99ecc0b](99ecc0b)), closes [#3528](#3528)
* **release:** update doctoc script ([e07c654](e07c654))
* **searchbox:** unmount component on dispose ([#3563](#3563)) ([c3f0435](c3f0435))
* **searchBox:** add reusable SearchBox component ([#3489](#3489)) ([c073a9a](c073a9a))

### Features

* **panel:** implement collapsed feature ([#3575](#3575)) ([e84b02b](e84b02b))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants