so what I am trying to do is, I want to pass the data collected in the header search bar to another component so that I can use it on that component as a query for the API I am going to use
the header component:
import ImageSearchIcon from '@material-ui/icons/ImageSearch';
import './Header.css'
function Header() {
const [query, setQuery] = useState("");
const handleSubmit = (event) => {
event.preventDefault();
}
return (
<div className="Header">
{/* LOGO */}
<div className="branding">
<ImageSearchIcon className="branding__logo" fontSize="large"/>
<h1>Image Finder</h1>
</div>
{/* Search Bar */}
<form onSubmit={handleSubmit}>
<input type="text" id="header__searchbar" placeholder="Search For Images" value={query} onChange={(e) => setQuery(e.target.value)} />
</form>
{/* USER ICON */}
<img className="user__image" src="https://www.pngitem.com/pimgs/m/150-1503945_transparent-user-png-default-user-image-png-png.png" alt="user__image" />
</div>
)
}
export default Header
the Second component:
import './Imagelist.css'
const Imagelist = () => {
return (
<div className="Imagelist">
</div>
)
}
export default Imagelist
CodePudding user response:
You can pass data between parent and child components in React using props
(think of props
as the parameters of components).
This is how passing props
looks like:
// Header component
const Header = () => {
// ... your logic
return (
<ImageList myProp={query} />
);
}
// ImageList component
const ImageList = ({ myProp }) => {
// now you can use myProp inside this component
};
You can get more information on props and React in general here.
CodePudding user response:
In addition to prop drilling (as mentioned by @Robfz): If you might use the prop in other components again (or also if your child component is very far from the parent), you could look into Context. This would allow you to pass your props down without having to pass it through every child in between.
CodePudding user response:
Lift state up to the parent component that a) performs the API request and manages the data, and b) renders both Header
and ImageList
.
App
maintains the main data state. It passes a handler to Header
that is called when the Header
button is clicked. When that handler is called the API is called and image JSON returned. The App
state is then updated with that (parsed) data.
ImageList
receives this data through a prop "images". It uses map to get the src
value from each returned object and return a new image.
Here's a brief working example explaining how I would approach this problem.
const { useState } = React;
// Sample JSON data
const json = '[{ "src": "https://dummyimage.com/100x100/77aa77/fff&text=Image" },{ "src": "https://dummyimage.com/100x100/7777aa/fff&text=Image" },{ "src": "https://dummyimage.com/100x100/aa7777/fff&text=Image" }]';
// Using a mock API to return some JSON
// after a two-second wait
function mockApi() {
return new Promise((res, rej) => {
setTimeout(() => res(json), 2000);
});
}
// ImageList receives an array of objects from App
// and maps over it creating a new image on each iteration
function ImageList({ images }) {
return (
<div className="imagelist">
{images.map(img => <img src={img.src} />)}
</div>
)
}
// App passes in the `handleUpdate` handler as a prop
function Header({ handleUpdate }) {
// Header maintains its own state for the input
const [input, setInput] = useState('');
// When the input changes we update the state
function handleChange(e) {
setInput(e.target.value);
}
// When the button is clicked the `handleUpdate`
// handler passed down from App is called with
// the current state
function handleClick() {
handleUpdate(input);
}
return (
<div>
Search: <input type="text" value={input} onChange={handleChange} />
<button onClick={handleClick}>Search</button>
</div>
);
}
function App() {
// Maintains the image state
const [images, setImages] = useState([]);
// When the button in Header is clicked this
// handler is called. It makes an API call with the
// value: fetch(`${endpoint}/${value}`), and then
// sets the state with the data
function handleUpdate(value) {
console.log(`Query: ${value}`);
mockApi()
.then(json => JSON.parse(json))
.then(data => setImages(data));
}
return (
<div>
<Header handleUpdate={handleUpdate} />
<ImageList images={images} />
</div>
);
};
ReactDOM.render(
<App />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>