React中如何实现筛选与搜索功能协同生效?代码优化求助
Let's break down what's going on here and fix the issues step by step—your core logic is solid, but there are a few asynchronous state handling and pattern issues causing the delay and potential bugs.
Key Issues Identified
Incorrect
setStateCallback Usage
In youronSearchChangemethod, you're immediately invokingthis.filtredInput()instead of passing it as a callback tosetState. SincesetStateis asynchronous, this means your filter function runs before thesearchstate is actually updated, leading to stale state and the delay you're seeing.Deriving State from State (Instead of Source Data)
Every time you runfiltredInput, you're starting with the originaljsondata—which is good! But storing filtered items in state is unnecessary because filtered results are derived state (they depend entirely on your source data + current filters/search term). Storing derived state can lead to unnecessary re-renders and state sync issues.Typos & Undefined Methods
filtredInputhas a typo (should befilteredInput—minor, but improves readability)updateShoppingBasketis passed to theFilteredcomponent but never defined in yourShopclass—this will throw an error when the component tries to use it.
Fixed Component Code
Here's the revised version with all issues addressed:
export default class Shop extends PureComponent { // Store original items as an instance property (not state, since it doesn't change) originalItems = json; state = { search: "", filters: [] }; onFilterChange = (event) => { const checkboxes = [...event.currentTarget.closest(".filter").getElementsByTagName("input")]; const filters = checkboxes.filter(checkbox => checkbox.checked).map(checkbox => checkbox.name); this.setState({ filters }); }; onSearchChange = ({ currentTarget }) => { this.setState({ search: currentTarget.value }); }; // Calculate filtered items on-the-fly (derived state, no need to store in state) getFilteredItems = () => { let items = [...this.originalItems]; // Apply filters first if (this.state.filters.length > 0) { items = items.filter(element => this.state.filters.every(key => element[key])); } // Apply search term if (this.state.search.length > 0) { const searchTerm = this.state.search.toLowerCase(); items = items.filter(item => item.name.toLowerCase().includes(searchTerm)); } return items; }; // Don't forget to define this method if Filtered component needs it! updateShoppingBasket = (item) => { // Add your shopping basket logic here console.log("Adding item to basket:", item); }; render() { const filteredItems = this.getFilteredItems(); return ( <div> <div className="navigation"> <Filter onFilterChange={this.onFilterChange} /> <Search onSearchChange={this.onSearchChange} /> </div> <Filtered items={filteredItems} updateShoppingBasket={this.updateShoppingBasket} /> </div> ); } }
What Changed & Why
- Removed filtered items from state: Instead, we calculate
filteredItemsdirectly in the render method usinggetFilteredItems. This eliminates unnecessarysetStatecalls and ensures we always use the latest source data + state values. - Fixed
setStatecallback: We no longer pass an immediate function call tosetState—since we're not storing filtered items in state anymore, we don't need the callback at all. React will re-render automatically whensearchorfiltersstate changes, andgetFilteredItemswill use the latest state values. - Simplified filter logic: Used
filter+mapinstead ofmapwith a conditional push—cleaner and more idiomatic JavaScript. - Added
updateShoppingBasket: Added a placeholder for this method so yourFilteredcomponent doesn't throw an error (replace the console log with your actual logic). - Improved search logic: Used
includes()instead ofindexOf() !== -1for better readability.
Additional Performance Tips
Since you're using PureComponent, the Filtered component will only re-render when its props change. By calculating filteredItems in the render method, we ensure that any change to search or filters will generate a new filteredItems array, triggering the correct re-render. If your originalItems is large, you could memoize the getFilteredItems result using a custom memoization function to avoid recalculating on every render unless search or filters change.
内容的提问来源于stack exchange,提问作者user12324754

