Fix search bar disappears on mobile (#18909)

This commit is contained in:
Adarsh Bhadauria 2023-01-09 14:21:40 +05:30 committed by GitHub
parent 26c72096ba
commit 876638194c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 6 deletions

View file

@ -25,7 +25,7 @@ export function SearchFormSync() {
// Server-side rendering of search results means the DOM node is destroyed everytime a search is performed,
// So we need to get the reference every time and use that for the parent in the portal.
const element = document.getElementById('mobile-search-container');
const mscElement = document.getElementById('mobile-search-container');
// The DOM element has changed because server-sde rendering returns new
// search results which destroys the existing search form in mobile view.
@ -33,17 +33,29 @@ export function SearchFormSync() {
// i.e. the container for the createPortal call in the render.
// If we do not unmount, it will result in an unmounting error that will throw as the
// container element (search form that was wiped out because of the new search results) no longer exists.
if (mobileSearchContainer && element !== mobileSearchContainer) {
if (mobileSearchContainer && mscElement !== mobileSearchContainer) {
unmountComponentAtNode(mobileSearchContainer);
}
// We need to delete the existing server-side rendered form because createPortal only appends to it's container.
if (element) {
const form = element.querySelector('form');
form && element.removeChild(form);
if (mscElement) {
const form = mscElement.querySelector('form');
// We remove the child form expecting that createPortal adds the new form on each re-render
form && mscElement.removeChild(form);
}
setMobileSearchContainer(element);
// Since, passing the reference to same element will not cause the component to re-render
// we CLONE & REPLACE the element with the clone & pass the clone's reference, so that useState
// will re-render the component.
const mscElementClone = mscElement ? mscElement.cloneNode(true) : null;
if (mscElementClone) {
const mscElementParent = mscElement.parentElement;
unmountComponentAtNode(mscElement);
mscElementParent.prepend(mscElementClone);
}
setMobileSearchContainer(mscElementClone);
setSearchTerm(updatedSearchTerm);
}

View file

@ -118,4 +118,26 @@ describe('<SearchFormSync />', () => {
expect(desktopSearch.value).toEqual(searchTerm2);
expect(mobileSearch.value).toEqual(searchTerm2);
});
it('ensure both mobile search form & desktop search form exists', async () => {
const { getAllByRole } = render(<SearchFormSync />);
setWindowLocation(`https://localhost:3000/search`);
// fire click event twice with empty query to mimic clicking search button twice present in header
for (let i = 0; i < 2; i += 1) {
fireEvent(
window,
new CustomEvent('syncSearchForms', {
detail: { querystring: window.location.search },
}),
);
}
const forms = await getAllByRole('textbox', {
name: /search/i,
});
expect(forms.length).toEqual(2);
});
});