如何在两层嵌套的React组件中更新根组件的state
Hey there! Let's fix this state management issue step by step. Since you're new to React, the simplest approach here is to use prop drilling (passing state and update functions down through components) — it's ideal for small component trees like yours. Here's how to adjust each component:
1. Update App.js: Pass State and Update Function to Listing
First, we'll add a method in App to handle category changes, then pass both the selectedCategory state and this method to the Listing component:
class App extends Component { state = { tours: {}, selectedCategory: "" }; loadData() { fetch(API) .then(response => response.json()) .then(json => { console.log(json); this.setState({ tours: json }); }); } // Add this method to update the selected category state handleCategoryChange = (categoryId) => { this.setState({ selectedCategory: categoryId }); // You can add filtering logic for tours here later, e.g.: // const filteredTours = this.state.tours.filter(tour => tour.categoryId === categoryId); // this.setState({ filteredTours }); } componentDidMount() { this.loadData(); } render() { return ( <div className="tour-container"> {/* Pass state and update function as props to Listing */} <Listing selectedCategory={this.state.selectedCategory} onCategoryChange={this.handleCategoryChange} /> </div> ); } } export default App;
2. Update Listing.js: Pass Props to Categories
Listing acts as a middleman here — it just needs to forward the props it receives from App to the Categories component:
import React, { Component } from 'react'; import Categories from './Categories.js'; class Listing extends Component { render() { const { selectedCategory, onCategoryChange } = this.props; return ( <div> {/* Forward props to Categories */} <Categories selectedCategory={selectedCategory} onCategoryChange={onCategoryChange} /> </div> ); } } export default Listing;
3. Update Categories.js: Use Props Instead of Local State
Remove the local selectedCategory state from Categories, and use the props to handle clicks and track the active category:
import React, { Component } from 'react'; class Categories extends Component { handleCategoryClick = (id, e) => { console.log(id); // Call the update function from props instead of setting local state this.props.onCategoryChange(id); } render() { const { selectedCategory } = this.props; return ( <div className="tour-categories"> <ul className="tour-categories-list"> {/* Add active class to the selected category */} <li onClick={(e) => this.handleCategoryClick(1, e)} className={selectedCategory === 1 ? 'active' : ''} >Food & Drink</li> <li onClick={(e) => this.handleCategoryClick(2, e)} className={selectedCategory === 2 ? 'active' : ''} >Whisky Distilleries</li> <li onClick={(e) => this.handleCategoryClick(3, e)} className={selectedCategory === 3 ? 'active' : ''} >TV & Film Location</li> <li onClick={(e) => this.handleCategoryClick(4, e)} className={selectedCategory === 4 ? 'active' : ''} >City Tour</li> <li onClick={(e) => this.handleCategoryClick(5, e)} className={selectedCategory === 5 ? 'active' : ''} >Castles</li> <li onClick={(e) => this.handleCategoryClick(6, e)} className={selectedCategory === 6 ? 'active' : ''} >Golf </li> <li onClick={(e) => this.handleCategoryClick(7, e)} className={selectedCategory === 7 ? 'active' : ''} >Shopping</li> <li onClick={(e) => this.handleCategoryClick(8, e)} className={selectedCategory === 8 ? 'active' : ''} >Out Door Activities</li> <li onClick={(e) => this.handleCategoryClick(9, e)} className={selectedCategory === 9 ? 'active' : ''} >Spa & Wellness</li> <li onClick={(e) => this.handleCategoryClick(10, e)} className={selectedCategory === 10 ? 'active' : ''} >Boat Tours & Water Sports</li> <li onClick={(e) => this.handleCategoryClick(11, e)} className={selectedCategory === 11 ? 'active' : ''} >Zoo & Aquariums</li> </ul> </div> ); } } export default Categories;
How This Works
- The
selectedCategorystate lives in the top-levelAppcomponent, where it can be used to filter thetoursdata later. - We pass the state and an update function (
onCategoryChange) down throughListingtoCategories. - When a category is clicked in
Categories, it triggers theonCategoryChangefunction, which updates the state inApp. - All components receive the updated state via props, so the selected category is consistent across the app.
For larger apps, you might look into state management libraries like Redux or React Context, but prop drilling is the simplest and most straightforward solution for your current setup.
内容的提问来源于stack exchange,提问作者user3725781

