I have a single page application, really simple (just trying stuff out to learn, so a complete beginner). I need to rerender a component when I change my state, and I do this with useEffect. But the function returns new HTML-code that I need to insert at a certain place in the code. How can I do this?
This is the basics of my app. I need to insert the HTML that displaySearchResult returns into the <div className="search-results-container">
function App() {
let [searchPhrase, setSearchPhrase] = useState("");
let [searchResults, setSearchResults] = useState({});
useEffect(() => {
displaySearchResult()
}, [searchResults])
const displaySearchResult = () => {
return searchResults.artists.items.map((artist) =>
<div className="search-result-item" onClick={() => searchSingleArtist(artist.id).then(response => setSingleArtistSearchResults(response))} key={artist.id}>
{artist.images.length > 0 &&
<img src={artist.images[0].url} alt="Artist"/>
}
{artist.images.length <= 0 &&
<img src={noImg} alt="No image avaliable" />
}
<b>{artist.name}</b>
</div>
)
}
return (
<div className="App">
<div className="App-container">
<div className="search-field-container">
<TextField value={searchPhrase} onInput={e => setSearchPhrase(e.target.value)} />
<Button
onClick={() => searchArtist(searchPhrase).then(response => setSearchResults(response))}>Search artist</Button>
</div>
<div className="search-results-container">
</div>
</div>
</div>
);
Please ignore some things that might look off, I cannot post the whole application here and therefore might have missed some stuff here. My app works, and my API-call works, I just need advice how to but the HTML in the container!
CodePudding user response:
useEffect
is not the right tool for this job. Instead, put that searchResults.artists.items.map
line inside the div where you want it to render. If the state might not exist to begin with, then you can check for that. For example, you can start off with a value of null
, then do searchResults && /* the stuff you want to render */
:
function App() {
let [searchPhrase, setSearchPhrase] = useState("");
let [searchResults, setSearchResults] = useState(null);
return (
<div className="App">
<div className="App-container">
<div className="search-field-container">
<TextField
value={searchPhrase}
onInput={(e) => setSearchPhrase(e.target.value)}
/>
<Button
onClick={() =>
searchArtist(searchPhrase).then((response) =>
setSearchResults(response)
)
}
>
Search artist
</Button>
</div>
<div className="search-results-container">
{searchResults && searchResults.artists.items.map((artist) => (
<div
className="search-result-item"
onClick={() =>
searchSingleArtist(artist.id).then((response) =>
setSingleArtistSearchResults(response)
)
}
key={artist.id}
>
{artist.images.length > 0 && (
<img src={artist.images[0].url} alt="Artist" />
)}
{artist.images.length <= 0 && (
<img src={noImg} alt="No image avaliable" />
)}
<b>{artist.name}</b>
</div>
))}
</div>
</div>
</div>
);
}
CodePudding user response:
You just have to call the function inside the JSX code. Since it will return a list of HTML elements (One per element). Inside the container div you could put your function like this,
{displaySearchResults()}