When I'm fetching data in my main page everything works as i wantend but when i'm fetching data in another folder using same code but with dynamic url i got a error when im trying to using methods on array. When i console.log fetched data i got the same array as in my main page
When i delete Link and only want to see book.title it works but i got error when i want to get data from resources
mainpage.js
const [data, setData] = useState(null);
const [isLoading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
fetch('https://gnikdroy.pythonanywhere.com/api/book')
.then((res) => res.json())
.then((data) => {
setData(data);
setLoading(false);
});
}, []);
return(
<div>
{data.results.map((book, index) => (
<div key={index}>
<h1>{book.title}</h1>
<Link href={`/reader/${book.id}`} passHref>
<h2>
{
book.resources.find(
({ type }) => type === 'application/epub zip'
).uri
}
</h2>
</Link>
</div>
))}
</div>
)
searchPage.js
const router = useRouter();
const { name } = router.query;
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
fetch(`https://gnikdroy.pythonanywhere.com/api/book/?search=${name}`)
.then((res) => res.json())
.then((data) => {
setData(data);
setLoading(false);
console.log(data);
});
}, []);
return(
<div>
{data.results.map((book, index) => (
<div key={index}>
<h1>{book.title}</h1>
<Link href={`/reader/${book.id}`} passHref>
<h2>
{
book.resources.find(
({ type }) => type === 'application/epub zip'
).uri
}
</h2>
</Link>
</div>
))}
</div>
)
my console.log inside fetch in searchPage.js console.log
CodePudding user response:
Your response data is not getting resources fields sometime.
That's why book.resources
can be undefined (or) null.
You can easily use Optional Changing(?.)
Replace:
{
book.resources?.find(
({ type }) => type === 'application/epub zip'
)?.uri || ''
}
CodePudding user response:
In addition to the Wu Woo's answer, When consider How React render your code,
First will execute the return
and then useEffect
only in page load since you're not having values in useEffect
Dependency array.
So in your scenario, you have data = null in initial page load. So when render below code, since data = null data.results
can't use Arrays.map().
Then will execute the useEffect
and inside there you set the value return from API call and set that value to data.
To avoid that render undefined error you must ensure data.results
are not equal to null/undefined and when there is data.results
render what you want.
You can achieve that by below ways.
The optional chaining operator (?.) as Wu Woo's answer which simplify accessing values through connected objects when it's possible that a reference or function may be
undefined or null
. Then it will not give above error whenbook.resources
equal null/undefined.render only when there is value for
data.results
andbook.resources
otherwise not like below.// Here conditionally check whether there is value for data?.results and if so render this. {data?.results && data.results.map((book, index) => ( <div key={index}> <h1>{book.title}</h1> <Link href={`/reader/${book.id}`} passHref> <h2> {/* Here also conditionally check whether there is value for book?.resources and if so render this. */} { book?.resources && book.resources.find( ({ type }) => type === 'application/epub zip' ).uri } </h2> </Link> </div> ))}