Explicit Data Fetching with React
Re-fetching all data each time someone types in the input field isn't optimal. Since we're using a third-party API to fetch the data, its internals are out of our reach. Eventually, we will be confronted with rate limiting which returns an error instead of data. To solve this problem, we will change the implementation details from implicit to explicit data (re-)fetching. In other words, the application will refetch data only if someone clicks a confirmation button.
Task: The server-side search executes every time a user types into the input field. The new implementation should only execute a search when a user clicks a confirmation button. As long as the button is not clicked, the search term can change but isn't executed as API request.
Optional Hints:
- Add a button element to confirm the search request.
- Create a stateful value for the confirmed search.
- The button's event handler sets confirmed search as state by using the current search term.
- Only when the new confirmed search is set as state, execute the side-effect to perform a server-side search.
What's important with this feature is that we need a state for the fluctuating searchTerm
and a new state for the confirmed search. But first of all, create a new button element which confirms the search and executes the data request eventually:
src/App.jsx
const App = () => {
...
return (
<div>
<h1>My Hacker Stories</h1>
<InputWithLabel
id="search"
value={searchTerm}
isFocused
onInputChange={handleSearchInput}
>
<strong>Search:</strong>
</InputWithLabel>
<button
type="button"
disabled={!searchTerm}
onClick={handleSearchSubmit}
>
Submit
</button>
...
</div>
);
};
Second, we distinguish between the handler of the input field and the button. While the renamed handler of the input field still sets the stateful searchTerm
, the new handler of the button sets the new stateful value called url
which is derived from the current searchTerm
and the static API endpoint as a new state:
src/App.jsx
const App = () => {
const [searchTerm, setSearchTerm] = useStorageState(
'search',
'React'
);
const [url, setUrl] = React.useState(
`${API_ENDPOINT}${searchTerm}`
);
...
const handleSearchInput = (event) => {
setSearchTerm(event.target.value);
};
const handleSearchSubmit = () => {
setUrl(`${API_ENDPOINT}${searchTerm}`);
};
...
};
Third, instead of running the data fetching side-effect on every searchTerm
change (which happens each time the input field's value changes like we have seen before), the new stateful url
is used whenever a user changes it by confirming a search request when clicking the button:
src/App.jsx
const App = () => {
...
const handleFetchStories = React.useCallback(() => {
dispatchStories({ type: 'STORIES_FETCH_INIT' });
fetch(url)
.then((response) => response.json())
.then((result) => {
dispatchStories({
type: 'STORIES_FETCH_SUCCESS',
payload: result.hits,
});
})
.catch(() =>
dispatchStories({ type: 'STORIES_FETCH_FAILURE' })
);
}, [url]);
React.useEffect(() => {
handleFetchStories();
}, [handleFetchStories]);
...
};
Before the searchTerm
was used for two cases: updating the input field's state and activating the side-effect for fetching data. Now it's only used for the former. A second state called url
got introduced for triggering the side-effect that fetches the data which only happens when a user clicks the confirmation button.
Exercises:
- Compare your source code against the author's source code.
- Recap all the source code changes from this section.
- Optional: If you are using TypeScript, check out the author's source code here.
- Optional: Leave feedback for this section.
Interview Questions:
- Question: Why is
useState
instead ofuseStorageState
used for theurl
state management?- Answer: We do not want to remember the
url
in the browser's local storage, because it's already derived from a static string (here:API_ENDPOINT
) and thesearchTerm
which already comes from the browser's local storage.
- Answer: We do not want to remember the
- Question: Why is there no check for an empty
searchTerm
in thehandleFetchStories
function anymore?- Answer: Preventing a server-side search happens in the new button, because it gets disabled whenever there is no
searchTerm
.
- Answer: Preventing a server-side search happens in the new button, because it gets disabled whenever there is no