React: sending useState results object to grandparent

This is currently my App.js return
> export default function App() {
> carList.forEach((car, i) => {
> car.id = i + 1;
> });
>
> const [results, setResults] = useState(carList);
> // const [menu, setMenu] = useState(false);
> return (
> <Router>
> <Header />
> <Switch>
> <Route path="/home">
> <CardList results={results} />
> </Route>
> </Switch>
> </Router>
> );
> }
> export default function App() {
> carList.forEach((car, i) => {
> car.id = i + 1;
> });
>
> const [results, setResults] = useState(carList);
> // const [menu, setMenu] = useState(false);
> return (
> <Router>
> <Header />
> <Switch>
> <Route path="/home">
> <CardList results={results} />
> </Route>
> </Switch>
> </Router>
> );
> }
<Header/> (below) has a 'menu' div that with a Searchbar & Filter component inside of it, which both filter a .json from user input and send a 'results' object , setResults(results);, to their parent <Header/>, where they're invoked.
const Header = ({ setResults }) => {
const [results, setResults] = useState(carList);
const [menu, setMenu] = useState(false);

carList.forEach((car, i) => {
car.id = i + 1;
});



return (
<>
<header>
<h1>Inventory Search</h1>
<div className="filter-container">
<div
className="menu-trigger"
onClick={() => {
setMenu(!menu);
}}
>
<button></button>
</div>
</div>
</header>

<div className={`dropdown-menu ${menu ? "active" : "inactive"}`}>
<Searchbar setResults={setResults} />
<Filter setResults={setResults} />
</div>
</>
);
};
const Header = ({ setResults }) => {
const [results, setResults] = useState(carList);
const [menu, setMenu] = useState(false);

carList.forEach((car, i) => {
car.id = i + 1;
});



return (
<>
<header>
<h1>Inventory Search</h1>
<div className="filter-container">
<div
className="menu-trigger"
onClick={() => {
setMenu(!menu);
}}
>
<button></button>
</div>
</div>
</header>

<div className={`dropdown-menu ${menu ? "active" : "inactive"}`}>
<Searchbar setResults={setResults} />
<Filter setResults={setResults} />
</div>
</>
);
};
Inside <Header> here, I've destructured useState to have a results to receive that results object.. which I could plug in to some html. However, instead of calling the results objects of <Searchbar/> & <Filter/> here, in <Header>, I want Header to send this received results object to its own parent, App.js.. so that I can use it with a separate <Cardlist> element.. a sibling to Header, that will be where the results are displayed, since I want my <Switch> to be below the <Header> GH: https://github.com/nnall/Inventory.git
GitHub
GitHub - nnall/Inventory
Contribute to nnall/Inventory development by creating an account on GitHub.
11 Replies
Rook
Rook2y ago
Hey! If I'm understanding this correctly, you are looking for a way to get the state from the Header component up to the App component. Instead of calling useState in the Header component, why not just pass the results as a prop to it from the App component? The App component is already storing the same exact data, there isn't a need to call useState again the the Header component.
thethingisback
"why not just pass the results as a prop to it from the App component? "
export default function App() {
carList.forEach((car, i) => {
car.id = i + 1;
});

const [results, setResults] = useState(carList);
// const [menu, setMenu] = useState(false);
return (
<Router>
<Header setResults={{ setResults }} />
<Switch>
<Route path="/home">
<CardList results={results} />
</Route>
</Switch>
</Router>
);
}
export default function App() {
carList.forEach((car, i) => {
car.id = i + 1;
});

const [results, setResults] = useState(carList);
// const [menu, setMenu] = useState(false);
return (
<Router>
<Header setResults={{ setResults }} />
<Switch>
<Route path="/home">
<CardList results={results} />
</Route>
</Switch>
</Router>
);
}
Am I passing the results object to the header here?
Rook
Rook2y ago
No, you are only passing setResults to the Header component, try passing both results and setResults and remove the useState from the Header component So something like <Header results={results} setResults={setResults} /> in your App component, and const Header = ({ results, setResults })...
thethingisback
const Header = ({ results, setResults }) => {
// const [results, setResults] = useState(carList);
const [menu, setMenu] = useState(false);

carList.forEach((car, i) => {
car.id = i + 1;
});

// const results =

// props(results);

return (
<>
<header>
<h1>Inventory Search</h1>
<div className="filter-container">
<div
className="menu-trigger"
onClick={() => {
setMenu(!menu);
}}
>
<button></button>
</div>
</div>
</header>

<div className={`dropdown-menu ${menu ? "active" : "inactive"}`}>
<Searchbar setResults={setResults} />
<Filter setResults={setResults} />
</div>
</>
);
};

export default Header;
const Header = ({ results, setResults }) => {
// const [results, setResults] = useState(carList);
const [menu, setMenu] = useState(false);

carList.forEach((car, i) => {
car.id = i + 1;
});

// const results =

// props(results);

return (
<>
<header>
<h1>Inventory Search</h1>
<div className="filter-container">
<div
className="menu-trigger"
onClick={() => {
setMenu(!menu);
}}
>
<button></button>
</div>
</div>
</header>

<div className={`dropdown-menu ${menu ? "active" : "inactive"}`}>
<Searchbar setResults={setResults} />
<Filter setResults={setResults} />
</div>
</>
);
};

export default Header;
But then how is the results getting assigned here? In order to take the results object into App.js? Its greyed out here This is my app.js
export default function App(props) {
carList.forEach((car, i) => {
car.id = i + 1;
});

const [results, setResults] = useState(carList);
// const [menu, setMenu] = useState(false);
return (
<Router>
<Header setResults={{ setResults }} results={{ results }} />
<Switch>
<Route path="/home">
<CardList results={results} />
</Route>
</Switch>
</Router>
);
}
export default function App(props) {
carList.forEach((car, i) => {
car.id = i + 1;
});

const [results, setResults] = useState(carList);
// const [menu, setMenu] = useState(false);
return (
<Router>
<Header setResults={{ setResults }} results={{ results }} />
<Switch>
<Route path="/home">
<CardList results={results} />
</Route>
</Switch>
</Router>
);
}
Rook
Rook2y ago
what do you mean by greyed out? it might be saying it's unused the key is that results isn't getting defined there, it's getting defined by its parent component App.
thethingisback
so, here for example, in the returned HTML of the Header component
<div className={`dropdown-menu ${menu ? "active" : "inactive"}`}>
<Searchbar setResults={setResults} />
<Filter setResults={setResults} />
</div>
<div className={`dropdown-menu ${menu ? "active" : "inactive"}`}>
<Searchbar setResults={setResults} />
<Filter setResults={setResults} />
</div>
Searchbar and Filter each inside them invoke a setResults(results)and that works to send the results object from each of those components, into their parent here in Header. Here, in Header, there is a destructured-from-useState 'results' object, which is automatically assigned to the results object coming from Searchbar or Filter, correct?
Rook
Rook2y ago
Kinda, yeah. Since results is declared in App, setResults will send the updated result all the way back up to App. The Header results object is referencing the App results object
thethingisback
This is the Header
const Header = ({ setResults }) => {
const [results, setResults] = useState(carList);
const [menu, setMenu] = useState(false);

carList.forEach((car, i) => {
car.id = i + 1;
});

setResults(results);

return (
<>
<header>
<h1>Inventory Search</h1>
<div className="filter-container">
<div
className="menu-trigger"
onClick={() => {
setMenu(!menu);
}}
>
<button></button>
</div>
</div>
</header>

<div className={`dropdown-menu ${menu ? "active" : "inactive"}`}>
<Searchbar setResults={setResults} />
<Filter setResults={setResults} />
</div>
</>
);
};

export default Header;
const Header = ({ setResults }) => {
const [results, setResults] = useState(carList);
const [menu, setMenu] = useState(false);

carList.forEach((car, i) => {
car.id = i + 1;
});

setResults(results);

return (
<>
<header>
<h1>Inventory Search</h1>
<div className="filter-container">
<div
className="menu-trigger"
onClick={() => {
setMenu(!menu);
}}
>
<button></button>
</div>
</div>
</header>

<div className={`dropdown-menu ${menu ? "active" : "inactive"}`}>
<Searchbar setResults={setResults} />
<Filter setResults={setResults} />
</div>
</>
);
};

export default Header;
This is App.js
export default function App(props) {
carList.forEach((car, i) => {
car.id = i + 1;
});

const [results, setResults] = useState(carList);
// const [menu, setMenu] = useState(false);
return (
<Router>
<Header setResults={results} />
<Switch>
<Route path="/home">
<CardList results={results} />
</Route>
</Switch>
</Router>
);
}
export default function App(props) {
carList.forEach((car, i) => {
car.id = i + 1;
});

const [results, setResults] = useState(carList);
// const [menu, setMenu] = useState(false);
return (
<Router>
<Header setResults={results} />
<Switch>
<Route path="/home">
<CardList results={results} />
</Route>
</Switch>
</Router>
);
}
I still don't get how to pass the results object as a prop to App.js
Rook
Rook2y ago
You aren't passing anything to App.js, you are passing things from App.js it looks like you just went back to what you had before
thethingisback
so my app.js
export default function App(props) {
carList.forEach((car, i) => {
car.id = i + 1;
});

const [results, setResults] = useState(carList);
// const [menu, setMenu] = useState(false);
return (
<Router>
<Header setResults={results} />
<Switch>
<Route path="/home">
<CardList results={results} />
</Route>
</Switch>
</Router>
);
}
export default function App(props) {
carList.forEach((car, i) => {
car.id = i + 1;
});

const [results, setResults] = useState(carList);
// const [menu, setMenu] = useState(false);
return (
<Router>
<Header setResults={results} />
<Switch>
<Route path="/home">
<CardList results={results} />
</Route>
</Switch>
</Router>
);
}
I have a props parameter in App.js.. So I need to setProps() or something? in order to pass .. something? downward to Header?
Rook
Rook2y ago
no i'm away from my computer right now, but i recommend reading up on prop drilling and what it means but if a component needs to update some state, that state needs to be stored higher on the component tree
Want results from more Discord servers?
Add your server