A little hard to explain, but please bear with me.
I have this function Component
. The function Component
code is almost the same, but how can i simplify my function MyComponent
with the return
value are different to each pages?
Below is my code and to better understand here is the complete sandbox code https://codesandbox.io/.
import { React, useState, useEffect } from "react";
function MyComponent() {
const [error, setError] = useState(null);
const [isLoaded, setIsLoaded] = useState(false);
const [items, setItems] = useState([]);
useEffect(() => {
fetch(
"https://api.unsplash.com/search/photos?query=nature?orientation=landscape&client_id=ddIh7_ebg4KwNHzNLf3ePCZb6yIPREJ5jxG3dYgoj6U"
)
.then((res) => res.json())
.then(
(result) => {
setIsLoaded(true);
setItems(result.results);
},
(error) => {
setIsLoaded(true);
setError(error);
}
);
}, []);
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div style={{ textAlign: "left" }}>
This return has to be dynamic. See the function Home and About below.
</div>
);
}
}
export default MyComponent;
Here is my Home and About pages.
function Home() {
const [items, setItems] = useState([]);
return (
<div>
<h2>Home</h2>
<ul>
{items.map((item) => (
<li key={item.id}>{item.user.last_name}</li>
))}
</ul>
</div>
);
}
function About() {
const [items, setItems] = useState([]);
return (
<div>
<h2>About</h2>
<ul>
{items.map((item) => (
<li key={item.id}>{item.user.first_name}</li>
))}
</ul>
</div>
);
}
MyComponent
doesn't appear to be rendered in my codesandbox, thats why im asking how can achieve my questions.
The issue is that you've no centralized source of truth. Each of MyComponent
, Home
, and About
each have their own items
state. The question you are asking is how to get the items
that MyComponent
fetched passed to the other two.
The solution is to Lift State Up. Move all the fetching and rendering logic from MyComponent
into App
. Pass the items
state down to both Home
and About
.
App
export default function App() {
const [error, setError] = useState(null);
const [isLoaded, setIsLoaded] = useState(false);
const [items, setItems] = useState([]);
useEffect(() => {
fetch(
"https://api.unsplash.com/search/photos?query=nature?orientation=landscape&client_id=ddIh7_ebg4KwNHzNLf3ePCZb6yIPREJ5jxG3dYgoj6U"
)
.then((res) => res.json())
.then((result) => {
setItems(result.results);
})
.catch((error) => {
setError(error);
})
.finally(() => {
setIsLoaded(true);
});
}, []);
return (
<BrowserRouter>
{<Layout />}
<main>
{error ? (
<div>Error: {error.message}</div>
) : !isLoaded ? (
<div>Loading...</div>
) : (
<React.Suspense fallback={<h6>Loading...</h6>}>
<Routes>
<Route path="/" element={<Home items={items} />} />
<Route path="/about" element={<About items={items} />} />
</Routes>
</React.Suspense>
)}
</main>
</BrowserRouter>
);
}
Home
function Home({ items }) {
return (
<div>
<h2>Home</h2>
<ul>
{items.map((item) => (
<li key={item.id}>{item.user.last_name}</li>
))}
</ul>
</div>
);
}
About
function About({ items }) {
return (
<div>
<h2>About</h2>
<ul>
{items.map((item) => (
<li key={item.id}>{item.user.first_name}</li>
))}
</ul>
</div>
);
}