Initially, useEffect is used to get data from the server and list it in a table. The records are paginated. When a user begins to type I make a debounced request to the server to search the database. When the data is returned I am setting the state and the table is updated to show the results. However, when the user clears the text field I want to show the initial list again as if they hadn't typed anything. It seems like this is what happens but it isn't loading the initial list but rather hitting the search endpoint again and returning all results. Do I need to run the initial useEffect again somehow instead?
What would be the best approach based on the below?
const [searchTerm, setSearchTerm] = useState();
const [data, setData] = useState([]);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
const ourRequest = axios.CancelToken.source();
const getBookings = async () => {
setIsLoading(true);
const response = await axios.get(
`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/v1/all?page=${pageNumber}&limit=20`, {
cancelToken: ourRequest.token,
}
);
setData(response.data);
setNumberOfPages(response.data.totalPages);
setIsLoading(false);
};
getBookings();
return () => {
ourRequest.cancel();
};
}, [pageNumber]);
// when user types
const handleChange = (event) => {
const {
value
} = event.target;
setSearchTerm(value);
handleSearch(value);
};
// search
const handleSearch = useCallback(
debounce(async (searchTerm) => {
const response = await axios.post(
`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/v1/search`, {
searchTerm: searchTerm
}
);
setData(response.data);
}, 500),
[]
);
<Form.Control
type="text"
placeholder="Search..."
value={searchTerm}
onChange={handleChange}
/>
CodePudding user response:
You can move getBookings
function out of useEffect
for the re-usage. Whenever your search input field is empty, you just fetch data again from it.
const [searchTerm, setSearchTerm] = useState();
const [data, setData] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const requestToken = useRef()
const getBookings = async () => {
setIsLoading(true);
const response = await axios.get(
`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/v1/all?page=${pageNumber}&limit=20`, {
cancelToken: requestToken.current.token,
}
);
setData(response.data);
setNumberOfPages(response.data.totalPages);
setIsLoading(false);
};
useEffect(() => {
requestToken.current = axios.CancelToken.source();
getBookings();
return () => {
requestToken.current.cancel();
};
}, [pageNumber]);
// when user types
const handleChange = (event) => {
const {
value
} = event.target;
setSearchTerm(value);
handleSearch(value);
};
// search
const handleSearch = useCallback(
debounce(async (searchTerm) => {
//if search input field is empty
if(!searchTerm) {
getBookings();
return; //stop other logic
}
const response = await axios.post(
`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/v1/search`, {
searchTerm: searchTerm
}
);
setData(response.data);
}, 500),
[]
);
<Form.Control
type="text"
placeholder="Search..."
value={searchTerm}
onChange={handleChange}
/>
About the warning you get, your value is moving from an undefined value to a defined value. In your case, it's possibly from searchTerm
state.
You should set an empty string as a default value for searchTerm
const [searchTerm, setSearchTerm] = useState('');