admin管理员组文章数量:1315788
I have buttons Apply Filters
and Reset Filters
. When I click Apply Filters
, it applies filters in the UI immediately, but when I click Reset Filters
, it only is clicked after being clicked two times. Here's the code:
import { useState, useEffect } from 'react';
import { getBusinesses } from '../api/DBRequests';
import categories from '../constants/categories';
const BusinessListPage = () => {
const [businesses, setBusinesses] = useState([]);
const [filters, setFilters] = useState({
category: '',
state: '',
minPrice: '',
maxPrice: '',
minRevenue: '',
maxRevenue: '',
});
const [sortBy, setSortBy] = useState('');
const [loading, setLoading] = useState(false);
useEffect(() => {
fetchBusinesses();
}, []);
const fetchBusinesses = async () => {
setLoading(true);
try {
const adjustedSortBy =
sortBy === 'asc' ? 'asc' : sortBy === 'desc' ? 'desc' : '';
const businesses = await getBusinesses(adjustedSortBy, filters);
setBusinesses(businesses);
} catch (error) {
console.error('Error fetching businesses:', error.message);
} finally {
setLoading(false);
}
};
const handleInputChange = (e) => {
const { name, value } = e.target;
setFilters((prevFilters) => ({ ...prevFilters, [name]: value }));
};
const handleResetFilters = () => {
setFilters({
category: '',
state: '',
minPrice: '',
maxPrice: '',
minRevenue: '',
maxRevenue: '',
});
setSortBy('');
fetchBusinesses();
};
return (
<div className="container-fluid mt-4">
<div className="row">
<div className="col-md-3">
<div className="bg-light border p-3">
<h5>Filters</h5>
<div className="mb-3">
<label htmlFor="category" className="form-label">
Category
</label>
<select
id="category"
name="category"
className="form-control"
value={filters.category}
onChange={handleInputChange}
>
<option value="">All Categories</option>
{categories.map((category, index) => (
<option key={index} value={category}>
{category}
</option>
))}
</select>
</div>
<button
className="btn btn-primary btn-block"
onClick={fetchBusinesses}
>
Apply Filters
</button>
<button
className="btn btn-secondary btn-block mt-2"
onClick={handleResetFilters}
>
Reset Filters
</button>
</div>
</div>
{/* Businesses List Section */}
<div className="col-md-9">
{loading && <p className="d-block mx-auto">Loading</p>}
<div className="row">
{businesses.length === 0 && !loading && (
<div className="col-12">
<p className="mt-4 text-center">No businesses found.</p>
</div>
)}
{businesses.map((business) => (
<div className="col-md-4 mb-4" key={business._id}>
<div className="card h-100">
<div className="card-body">
<h5 className="card-title">{business.name}</h5>
</div>
<div className="card-footer">
<a
href={`/business/${business._id}`}
className="btn btn-primary btn-sm btn-block"
>
View Details
</a>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</div>
);
};
export default BusinessListPage;
I have buttons Apply Filters
and Reset Filters
. When I click Apply Filters
, it applies filters in the UI immediately, but when I click Reset Filters
, it only is clicked after being clicked two times. Here's the code:
import { useState, useEffect } from 'react';
import { getBusinesses } from '../api/DBRequests';
import categories from '../constants/categories';
const BusinessListPage = () => {
const [businesses, setBusinesses] = useState([]);
const [filters, setFilters] = useState({
category: '',
state: '',
minPrice: '',
maxPrice: '',
minRevenue: '',
maxRevenue: '',
});
const [sortBy, setSortBy] = useState('');
const [loading, setLoading] = useState(false);
useEffect(() => {
fetchBusinesses();
}, []);
const fetchBusinesses = async () => {
setLoading(true);
try {
const adjustedSortBy =
sortBy === 'asc' ? 'asc' : sortBy === 'desc' ? 'desc' : '';
const businesses = await getBusinesses(adjustedSortBy, filters);
setBusinesses(businesses);
} catch (error) {
console.error('Error fetching businesses:', error.message);
} finally {
setLoading(false);
}
};
const handleInputChange = (e) => {
const { name, value } = e.target;
setFilters((prevFilters) => ({ ...prevFilters, [name]: value }));
};
const handleResetFilters = () => {
setFilters({
category: '',
state: '',
minPrice: '',
maxPrice: '',
minRevenue: '',
maxRevenue: '',
});
setSortBy('');
fetchBusinesses();
};
return (
<div className="container-fluid mt-4">
<div className="row">
<div className="col-md-3">
<div className="bg-light border p-3">
<h5>Filters</h5>
<div className="mb-3">
<label htmlFor="category" className="form-label">
Category
</label>
<select
id="category"
name="category"
className="form-control"
value={filters.category}
onChange={handleInputChange}
>
<option value="">All Categories</option>
{categories.map((category, index) => (
<option key={index} value={category}>
{category}
</option>
))}
</select>
</div>
<button
className="btn btn-primary btn-block"
onClick={fetchBusinesses}
>
Apply Filters
</button>
<button
className="btn btn-secondary btn-block mt-2"
onClick={handleResetFilters}
>
Reset Filters
</button>
</div>
</div>
{/* Businesses List Section */}
<div className="col-md-9">
{loading && <p className="d-block mx-auto">Loading</p>}
<div className="row">
{businesses.length === 0 && !loading && (
<div className="col-12">
<p className="mt-4 text-center">No businesses found.</p>
</div>
)}
{businesses.map((business) => (
<div className="col-md-4 mb-4" key={business._id}>
<div className="card h-100">
<div className="card-body">
<h5 className="card-title">{business.name}</h5>
</div>
<div className="card-footer">
<a
href={`/business/${business._id}`}
className="btn btn-primary btn-sm btn-block"
>
View Details
</a>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</div>
);
};
export default BusinessListPage;
Share
Improve this question
edited Jan 30 at 3:25
in43sh
asked Jan 30 at 3:20
in43shin43sh
9432 gold badges14 silver badges37 bronze badges
8
|
Show 3 more comments
2 Answers
Reset to default 2Calling setFilters()
is asynchronous. Setting it to empty values and immediately calling fetchBusinesses()
doesn't give the filters state time to update.
I'd change fetchBusinesses()
to accept the filters
and sortBy
as parameters instead of relying on state. Then you can directly control the values; create an "empty filters" object then pass it to both fetchBusinesses()
and setFilters()
const initFilters = {
category: '',
state: '',
minPrice: '',
maxPrice: '',
minRevenue: '',
maxRevenue: '',
};
const initSortBy = '';
const BusinessListPage = () => {
const [filters, setFilters] = useState(initFilters);
const [sortBy, setSortBy] = useState(initSortBy);
// etc ...
// added params with default values coming from state
const fetchBusinesses = async (f = filters, s = sortBy) => {
setLoading(true);
try {
const adjustedSortBy =
s === 'asc' ? 'asc' : s === 'desc' ? 'desc' : '';
setBusinesses(await getBusinesses(adjustedSortBy, f));
} catch (error) {
console.error('Error fetching businesses:', error.message);
} finally {
setLoading(false);
}
};
const handleResetFilters = () => {
setFilters(initFilters);
setSortBy('');
fetchBusinesses(initFilters, ''); // pass in init values
};
https://react.dev/reference/react/StrictMode
React strict mode renders your object twice to catch potential bugs early on. This is why you need to "Reset Filters" twice to see it clear up.
Additionally, in useState, if you use strict mode "React will call your initializer function twice in order to help you find accidental impurities." - https://react.dev/reference/react/useState
Another possibility is that your function all "Reset filters" encounters an asynchronous process and waits for it to finish before setting the business.
const businesses = await getBusinesses(adjustedSortBy, filters);
本文标签: javascriptReset Filters button only updates UI after second clickStack Overflow
版权声明:本文标题:javascript - Reset Filters button only updates UI after second click - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741987513a2408770.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
setFilters()
is asynchronous. Setting it to empty values and immediately callingfetchBusinesses()
doesn't give thefilters
state time to update – Phil Commented Jan 30 at 3:37fetchBusinesses()
to accept thefilters
andsortBy
as parameters instead of relying on state. Then you can directly control the values; create an "empty filters" object then pass it to bothfetchBusinesses()
andsetFilters()
– Phil Commented Jan 30 at 3:47useEffect(fetchBusinesses, [appliedFilters])
– Phil Commented Jan 30 at 4:10