I have a button and an input box where upon submitting the input, a search will be run on the searchTerm and a table of results is displayed. I put the searchTerm as a dependency inside useEffect() so that the search will only be run if the searchTerm changes. Since useEffect() gets run when the window is opened, I added a check to see if searchTerm > 0 so the search is not performed when the window is opened.
However by doing this, the table rows are not updated upon the first search but the second search. If I remove the if (searchTerm.length > 0)
check, the table will populate as expected on first search (although it will run a search on the empty searchTerm right away which isn't ideal).
export const SearchWindow: React.FC<Props> = props => {
const documentationIndexState = useSelector((store: StoreState) => store.documentationIndex);
const dispatch = useDispatch();
const [searchInput, setSearchInput] = React.useState(''); // value inside input box
const [searchTerm, setSearchTerm] = React.useState(''); // term to search (set once search clicked)
React.useEffect(() => {
console.log('in useEffect with searchTerm len: ' searchTerm.length);
if (searchTerm.length > 0) {
console.log('len > 0, running search');
getSearchResults(props.config, searchTerm, documentationIndexState, dispatch).then(async searchResults => {
const rows = searchResults.map(result => {
return {
cells: {
source: documentationIndexState.headerReference.find(x => x.id === result.id)!.source,
},
};
});
dispatch(setSearchResults(rows));
});
}
}, [searchTerm]); // Only run search if searchTerm changes
return (
<div>
<form>
<input
placeholder='Enter Search Term'
onChange={e => setSearchInput(e.target.value)}
value={searchInput}
/>
<button
onClick={e => {
e.preventDefault();
setSearchTerm(searchInput);
}}
>
Search
</button>
</form>
</div>
<DataTable
rows={documentationIndexState.searchResults}
/>
...
CodePudding user response:
Is this what you're trying to achieve?
const [loaded, setLoaded] = React.useState(false);
React.useEffect(() => {
if (!loaded) {
setLoaded(true);
return;
}
console.log('in useEffect with searchTerm len: ' searchTerm.length);
if (searchTerm.length > 0) {
console.log('len > 0, running search');
getSearchResults(props.config, searchTerm, documentationIndexState, dispatch).then(async searchResults => {
const rows = searchResults.map(result => {
return {
cells: {
source: documentationIndexState.headerReference.find(x => x.id === result.id)!.source,
},
};
});
dispatch(setSearchResults(rows));
});
}
}, [searchTerm]); // Only run search if searchTerm changes & loaded is true
CodePudding user response:
The callback for your search button should execute the search.
function Form() {
const [searchInput, setSearchInput] = React.useState('');
const runSearch = React.useCallback(
() => {
console.info('Searching', searchInput)
},
[searchInput]
);
return (
<form>
<h1> The form! </h1>
<input
placeholder='Enter Search Term'
onChange={e => setSearchInput(e.target.value)}
/>
<button
type="button"
onClick={runSearch}
>
Search
</button>
</form>
);
}
ReactDOM.createRoot(
document.getElementById('app')
).render(
React.createElement(Form)
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
<div id="app">
</div>