I am using the experimental next.js (ver.13)
Trying to understand what is wrong with my code .. as i am not getting anything and i am simply following the documentation.
it errors : photos.map is not a function
async function getPhotos() {
const res = await fetch('https://jsonplaceholder.typicode.com/photos');
return res.json();
}
export default function Photos() {
const photos = getPhotos();
return (
<div>
{photos.map((photo) => {
return <div key={photo.id}>{photo.title}</div>;
})}
</div>
);
}
Make the Photos component async aswell. It's also a good idea to use conditional chaining ?. on the photos array, so if in any case it is undefined, it doesn't throw an error
async function getPhotos() {
const res = await fetch('https://jsonplaceholder.typicode.com/photos');
return res.json();
}
export default async function Photos() {
const photos = await getPhotos();
return (
<div>
{photos?.map((photo) => {
return <div key={photo.id}>{photo.title}</div>;
})}
</div>
);
}
from here
if your node version is above 18
module.exports = {
experimental: {
enableUndici: true
}
}
Related
I am trying to use UseParam to get the id, i am trying to place it inside of my API request however when i console.log it the actual value doesn't go inside rather the text itself.
vesselComponents.js :
function VesselComponents() {
const { id } = useParams();
const api = async () => {
try {
const res = await axios.get(
// here
`http://127.0.0.1:8000/api/maintenance/${id}`
);
return res.data;
} catch (error) {
console.log(error);
}
};
console.log(api);
const { components, error, loading } = useSelector(
(state) => state.components
);
const dispatch = useDispatch();
useEffect(() => {
fetchComponents()(dispatch);
}, [dispatch]);
const getTreeItemsFromData = (treeItems) => {
return treeItems.map((treeItemData) => {
let children = undefined;
if (treeItemData.children && treeItemData.children.length > 0) {
children = getTreeItemsFromData(treeItemData.children);
}
return (
<TreeItem
component={Link}
to={`./info/${treeItemData.id}`}
key={treeItemData.id}
nodeId={String(treeItemData.id)}
label={treeItemData.name}
children={children}
/>
);
});
};
const DataTreeView = ({ treeItems }) => {
return (
<TreeView
defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpandIcon={<ChevronRightIcon />}
>
{getTreeItemsFromData(treeItems)}
</TreeView>
);
};
return (
<div className="components-container">
<div className="components-items">
<DataTreeView treeItems={components} />
</div>
<div className="component-detail">
<Outlet />
</div>
</div>
);
}
export default VesselComponents;
This is how the console.log look like :
async () => {
try {
const res = await axios__WEBPACK_IMPORTED_MODULE_3___default().get( // here
`http://127.0.0.1:8000/api/maintenance/${id}`);
return res.data;
} catch (err…
Also if i wanted to make this call rather in my slice how would i go about exporting this specific ID that changes so i can use it there.
This is because you actually log the function, not the return value.
I suppose you want to fetch the maintenance id as the component mounts. I advice you to use useEffect for this case.
import { useEffect, useState } from 'react'; // above the component's class declaration
// and inside your component
const [api, setApi] = useState(null); // null by default
useEffect(() => {
const fetchMaintenance = async () => {
try {
const res = await axios.get(
// here
`http://127.0.0.1:8000/api/maintenance/${id}`
);
return res.data;
} catch (error) {
throw Error(error);
}
});
};
fetchMaintenance()
.then((api) => {
setApi(api);
})
.catch((error) => {
console.log(error);
});
}, []);
And by that you can use the value of api anywhere you like.
For example to log it
useEffect(() => {
console.log(api);
}, [api]);
or to render it on your view
return (
return (
<div className="components-container">
{JSON.stringify(api)}
<div className="components-items">
<DataTreeView treeItems={components} />
</div>
<div className="component-detail">
<Outlet />
</div>
</div>
);
}
I'm trying to learn Next.JS and after learning about getStaticPaths() I wanted to use it in a 'real life example'. However, contrary to the examples made with JSONPlaceholder it seems that I can't get it to work, and instead I get a 404 error with no messages whatsoever. So I wanted to ask what am I doing wrong:
is it the code itself (there's an error I can't see)
is it the approach itself?
index.js
import Link from 'next/dist/client/link';
const CHAMPIONS_URL =
'https://raw.communitydragon.org/latest/plugins/rcp-be-lol-game-data/global/default/v1/champion-summary.json';
export async function getStaticProps() {
const res = await fetch(CHAMPIONS_URL);
const champions = await res.json();
return {
props: { champions },
};
}
const Champions = ({ champions }) => {
// console.log(champions);
return (
<ul>
{champions.slice(1).map((champion) => (
<li key={champion.id}>
<Link href={`/champions/${champion.name}`}>{champion.name}</Link>
</li>
))}
</ul>
);
};
export default Champions;
[id].js
const CHAMPIONS_URL =
'https://raw.communitydragon.org/latest/plugins/rcp-be-lol-game-data/global/default/v1/champion-summary.json';
function getChampion(champion) {
return `https://raw.communitydragon.org/latest/plugins/rcp-be-lol-game-data/global/default/v1/champions/${champion}.json`;
}
export async function getStaticPaths() {
const res = await fetch(CHAMPIONS_URL);
const champions = await res.json();
const paths = champions.map((champion) => ({ params: { id: champion.id.toString() } }));
return { paths, fallback: false };
}
export async function getStaticProps({ params }) {
const res = await fetch(getChampion(params.id));
const champion = await res.json();
return { props: { champion } };
}
const Champion = ({ champion }) => {
console.log(champion);
return <div>Champion</div>;
};
export default Champion;
Your approach is fine. The 404 error you're seeing doesn't originate from Next.js itself, but from the external endpoint inside your getChampion() function in ./pages/champions/[id].js (and make sure [id].js exists in a directory named champions).
Passing champion.name to ${champion}.json will result in an error after interpolation since you're expecting to use params.id:
https://raw.communitydragon.org/latest/plugins/rcp-be-lol-game-data/global/default/v1/champions/Annie.json
But passing champion.id instead will work:
https://raw.communitydragon.org/latest/plugins/rcp-be-lol-game-data/global/default/v1/champions/1.json
So you really just need to change your <Link> component in .pages/index.js from...
{/* if you use `name` this will error */}
<Link href={`/champions/${champion.name}`}>{champion.name}</Link>
...to:
{/* but if you use `id` (since your page is named `[id].js`) this should work */}
<Link href={`/champions/${champion.id}`}>{champion.name}</Link>
I am trying to do getServerSideProps but I am getting the following error what is the error I am doing
TypeError: Cannot read properties of undefined (reading 'map')
import React from "react";
import axios from "axios";
import { useState, useEffect } from "react";
import { FormControl, Button } from "react-bootstrap";
import Card from "react-bootstrap/Card";
export default function Answershooks(props, { posts }) {
return (
<div className="answerhook">
{posts.map((personData, index) => {
return (
<Card key={index} className="cardmobile">
<Card.Body>
<p className="answersize">{personData.Answers} </p>
</Card.Body>
</Card>
);
})}
</div>
);
}
export async function getServerSideProps(ctx) {
const res = await fetch("https://askover.wixten.com/answersapi/" + props.id);
console.log(res);
console.log("dada");
const posts = await res.json();
// By returning { props: { posts } }, the Blog component
// will receive `posts` as a prop at build time
return {
props: {
posts,
},
};
}
i have added added a file stucture screenshot so u undersand how my files are placed
Your main problem is you're trying to call getServerSideProps in Answerhooks but it's not a page component, so you cannot get data on the server as expected
Instead of having getServerSideProps in that, you can move your API call to getServerSideProps in [itmid].jsx (which is an actual page component) like below
export async function getServerSideProps(ctx) {
var id = ctx.query.itmid;
const queryRequest = fetch("https://ask-over.herokuapp.com/questone/" + id).then(async (res) => await res.json());
const answerRequest = fetch("https://askover.wixten.com/answersapi/" + id).then(async (res) => await res.json());
const [posts, answerPosts] = await Promise.all([queryRequest, answerRequest]);
return {
props: {
posts,
answerPosts
}
};
}
After that, you can get answerPosts from props for Query
function Query({ posts, answerPosts }) {
return <Answerhooks answerPosts={answerPosts} />
}
Finally, you can have the data on props inside Answerhooks component
function Answershooks({ answerPosts }) {
//TODO: Apply your logic with `answerPosts`
console.log(answerPosts)
return <div></div>
}
Lets start with the fetch error and work out why that is failing so make a new component.
fetchHandler.js
export async function fetchHandler(url){
try{
const res = await fetch(url);
return res
} catch(err){
console.log(err); //this will tell us why it failed.
return false //this gives us a condition we can use on the front end
}
}
Then your Answerhooks.
import {fetchHandler} from '../yourpath'
export default function Answershooks({ posts }) {
return (
<div className="answerhook">
{posts.map((personData, index) => {
return (
<Card key={index} className="cardmobile">
<Card.Body>
<p className="answersize">{personData.Answers} </p>
</Card.Body>
</Card>
);
})}
</div>
);
}
export async function getServerSideProps(ctx) {
const url = `https://askover.wixten.com/answersapi/${ctx.query.id}`
const res = await fetchHandler(url)
console.log(res);
const posts = await res.json();
return {
props: {
posts: posts === false ? [] : posts //Just to stop your app crashing
},
};
}
export const getServerSideProps = wrapper.getServerSideProps(
(store) =>
async ({req}) => {
const result = await store.dispatch(fetchHome());
return {
props: {
list : result
},
};
}
);
I'm creating a page that will call my API route to return the value from my collection using MongoDB. But I'm having this error of Objects are not valid as a React child. I don't know why this happening. Can you please help me?
pages/index.js
export const getServerSideProps = async () => {
const res = await fetch('http://localhost:3000/api/listings');
const data = await res.json();
if (!data) {
return {
notFound: true,
};
}
return { props: { data } };
};
const index = async ({ data }) => {
return (
<>
<section className='w-screen h-screen bg-hero-pattern bg-cover bg-no-repeat bg-bottom'></section>
{data.map((prop) => (
<div key={prop._id}>
<h1>{prop.name}</h1>
<h2 className='text-2xl truncate'>{prop.summary}</h2>
<p>{prop.description}</p>
</div>
))}
</>
);
};
pages/api/listings
import { connectToDatabase } from '../../middlewares/mongodb';
export const fetchDbData = async () => {
const { db } = await connectToDatabase();
const data = await db
.collection('listingsAndReviews')
.find({})
.limit(1)
.toArray();
return JSON.parse(JSON.stringify(data));
};
export default async (req, res) => {
const data = await fetchDbData();
res.status(200).json(data);
};
For this project, I am attempting to transfer the data I have received from the API (a list of albums) and send them to another module in order to display the results based on whichever user has been selected. I'm using "useEffect()" in tandem with the "setAlbums()" function to set and send the album list data through a prop labeled "album". The problem is I am not receiving the data in the other module "AlbumList.js", so I can't display the user's album list. Can anyone find a solution to this? Please forgive all the logs, I'm new to working with React and have been trying to sort this out. Thanks so much for taking the time.
Here is the App.js file:
// App.js
import "./App.css";
import AlbumList from "./AlbumList";
import UserList from "./UserList";
function App() {
const controller = new AbortController();
const [users, setUsers] = useState([]);
const [user, setCurrentUser] = useState({});
const [albums, setAlbums] = useState([]);
document.title = 'Awesome Album App';
const userUrl = "https://jsonplaceholder.typicode.com/users";
// Loading Albums
useEffect(() => {
const albumUrl = `https://jsonplaceholder.typicode.com/albums?userId=${user.id}`;
async function loadAlbums() {
try {
const response = await fetch(albumUrl, { signal: controller.signal });
const json = await response.json();
console.log("Logging json: ", json)
setAlbums(json)
} catch (err) {
if (err.name === 'AbortError') {
console.log('Aborted', err)
} else {
throw err;
}
}
}
loadAlbums();
console.log("After loadAlbums: ", albums)
return () => {
controller.abort();
}
},[user])
// Loading Users
useEffect(() => {
async function loadUser() {
try {
const response = await fetch(userUrl, { signal: controller.signal });
const data = await response.json();
setUsers(...users, data);
} catch (err) {
if (err.name === 'AbortError') {
console.log('Aborted', err)
setUsers([])
} else {
throw err;
}
}
}
loadUser();
return () => {
controller.abort();
}
},[])
// Return JSX
return (
<div className="App">
<div className="left column">
<UserList users={users} setCurrentUser={setCurrentUser} />
</div>
<div className="right column">
<AlbumList user={user} album={album} />
</div>
</div>
);
}
export default App;
Here is the component that displays the albums:
// AlbumList.js
import React from "react";
function AlbumList({ user = {} }, albums) {
console.log("Logging inside of albumsList", albums)
if (albums.length) {
return albums.map((album, index) => {
return <li key={index}>{album.id}{album.title}</li>;
});
}
return (
<div>
<p>Please click on a user name to the left</p>
</div>
);
}
export default AlbumList;```
Is it because you are passing album={album} to the <AlbumList /> component when it should be albums={albums}? I'm not sure if this was just an error when you were transferring your code to Stack Overflow, but <AlbumList/> expects a prop of albums whereas you passed an album prop. Though, I'm curious as to why the compiler didn't throw an error for album not being defined - from what I can see, you only have the albums variable defined. Also, I believe you need to destructure the props in AlbumList.js like so
function AlbumList({ user = {} , albums}) {
(i.e. } should appear after the albums prop).