search: Restructure "sync query from URL" logic
Created by: fkling
tl;dr: Instead of relying on a couple of useEffect
s in multiple components
to sync/update the search query from the URL we are now listening to URL
changes in the app root and update the store directly from there.
It's possible that in some obscure situations the React effect for updating the query state doesn't happen. But there is also a more general issue with how we sync the query information from the URL to the app state, which causes multiple re-renders and "flashing" of the query in the search query input.
The "flashing" happens because we use useEffect
in a lot of places to
trigger updates to the search query store. useEffect
callbacks are
executed after the component has already rendered, which is too late.
I tried various things moving the "URL to store" syncing logic to various places, but all of them had some issues. The two main issues are:
- Query information is used in multiple places, so ideally the store is update before any component that depends on it is rendered. That means a store update should be triggered close to the root component.
- When syncing is tried to component re-rendering we restrict ourselves to updating the store after the containing component renders. We cannot update the store while the component re-renders because that would cause other components to update which causes a React error.
Eventually I ended up attaching a handler that listens to location changes
in the web app root and updates the query store accordingly, which I think
makes the most sense, at least for the time being. This causes the store to
be updated independently of component re-rendering.
The logic for updating the query and the search context, which was previously
contained in Layout.tsx
and GlobalNavbar.tsx
, is now located in a single
place.
I'm still not very happy about the fact that updateQueryStateFromLocation
directly calls out to useNavbarQueryState
but it did make it easier to write
tests that cover all the cases. I'll likely revisit this at some point.
Before/after video:
https://user-images.githubusercontent.com/179026/189132525-c4409f68-48c8-4c04-b4d9-f0825fdd8c9d.mp4
Test plan
To (not) reproduce the "empty input bug":
- Open Sourcegraph in a window that's < 1000px wide. It should show the collapsed menu bar.
- Increase size to see full menu bar.
- Enter and submit search query on search homepage
- The query input should contain the query on the results page
index.test.ts
(which was renamed from index.test.tsx
) contains additional
unit tests.
App preview:
Check out the client app preview documentation to learn more.