From e2ba45bb39bd744454ee599bdc2df497c79d9707 Mon Sep 17 00:00:00 2001 From: Ruslan Lesiutin <28902667+hoxyq@users.noreply.github.com> Date: Wed, 10 Sep 2025 18:38:47 +0100 Subject: [PATCH] [DevTools] fix: keep search query in a local sync state (#34423) When the search query changes, we kick off a transition that updates the search query in a reducer for TreeContext. The search input is also using this value for an `input` HTML element. For a larger applications, sometimes there is a noticeable delay in displaying the updated search query. This changes the approach to also keep a local synchronous state that is being updated on a change callback. --- .../views/Components/ComponentSearchInput.js | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Components/ComponentSearchInput.js b/packages/react-devtools-shared/src/devtools/views/Components/ComponentSearchInput.js index f84e29bf73..654fe76918 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/ComponentSearchInput.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/ComponentSearchInput.js @@ -8,22 +8,34 @@ */ import * as React from 'react'; -import {useContext} from 'react'; -import {TreeDispatcherContext, TreeStateContext} from './TreeContext'; +import {useState, useContext, useCallback} from 'react'; -import SearchInput from '../SearchInput'; +import SearchInput from 'react-devtools-shared/src/devtools/views/SearchInput'; +import { + TreeDispatcherContext, + TreeStateContext, +} from 'react-devtools-shared/src/devtools/views/Components/TreeContext'; -type Props = {}; +export default function ComponentSearchInput(): React.Node { + const [localSearchQuery, setLocalSearchQuery] = useState(''); + const {searchIndex, searchResults} = useContext(TreeStateContext); + const transitionDispatch = useContext(TreeDispatcherContext); -export default function ComponentSearchInput(props: Props): React.Node { - const {searchIndex, searchResults, searchText} = useContext(TreeStateContext); - const dispatch = useContext(TreeDispatcherContext); - - const search = (text: string) => - dispatch({type: 'SET_SEARCH_TEXT', payload: text}); - const goToNextResult = () => dispatch({type: 'GO_TO_NEXT_SEARCH_RESULT'}); - const goToPreviousResult = () => - dispatch({type: 'GO_TO_PREVIOUS_SEARCH_RESULT'}); + const search = useCallback( + (text: string) => { + setLocalSearchQuery(text); + transitionDispatch({type: 'SET_SEARCH_TEXT', payload: text}); + }, + [setLocalSearchQuery, transitionDispatch], + ); + const goToNextResult = useCallback( + () => transitionDispatch({type: 'GO_TO_NEXT_SEARCH_RESULT'}), + [transitionDispatch], + ); + const goToPreviousResult = useCallback( + () => transitionDispatch({type: 'GO_TO_PREVIOUS_SEARCH_RESULT'}), + [transitionDispatch], + ); return ( );