i've get problem in my project code.
I develop website for Online Shop purpose, honestly i'm using template from GitHub for faster production ( My lecture said ). Product working as well but Categories can't working as my expectation.
I'm using Next.js and this first time use FullStack on JavaScript. I'm wanna call my API from MongoDB with Axios and there have categories field within data type Array. This file i haven't change anyword.
Error said :
Cannot read property 'items' of undefined
This my line code inventoryByCategory.js :
function inventoryByCategory (inventory) {
return inventory.reduce((acc, next) => {
const categories = next.categories
categories.forEach(c => {
if (acc[c]) {
acc[c].items.push(next)
} else {
acc[c] = {}
acc[c].items = []
acc[c].items.push(next)
}
})
return acc
}, {})
}
export {
inventoryByCategory
}
This my data fecthing on inventoryProvider.js
import axios from "axios"
async function fetchInventory() {
const inventory = await axios.get('http://localhost:3000/api/inventory')
.then((response) => response.data.data)
return Promise.resolve(inventory)
}
export {
fetchInventory
}
And this my error show up in inventoryForCategory.js :
import { fetchInventory } from './inventoryProvider'
import { inventoryByCategory } from './inventoryByCategory'
async function inventoryForCategory (category) {
const inventory = await fetchInventory()
const byCategory = inventoryByCategory(inventory)
return byCategory[category].items
}
export default inventoryForCategory
I think this enough information for you, thanks in advance :)
Related
I am learning Next.js - version 13 and I try to customize the next.js app base on the standard document. But somehow, the middleware is not called. I assume I do something wrong here. If you have a time, please review the issue.
Here is the code change of middleware.ts:
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { AUTHORIZATION_TOKEN, COOKIE_TOKEN } from "#libs/constants";
import { verify } from "#libs/token";
export const config = {
matcher: ["/admin/:path*", "/signin", "/api/:path*"],
};
export async function middleware(request: NextRequest) {
const url = request.nextUrl.clone();
const regex = new RegExp('\\/api\\/(category|product|cart|coupon|auth)\\/(create|update|delete)', 'i')
let matcher: any = regex.exec(url.pathname);
let token: any;
let isValidToken: any;
if (matcher && matcher[0]) {
token = request.headers.get(AUTHORIZATION_TOKEN);
isValidToken = await verify(token);
} else {
token = request.cookies.get(COOKIE_TOKEN)?.value;
if (token) {
isValidToken = await verify(JSON.parse(token));
}
if (url.pathname.startsWith("/admin")) {
if (isValidToken) {
return NextResponse.next();
} else {
url.pathname = "/signin";
return NextResponse.redirect(url);
}
}
if (url.pathname.startsWith("/signin") && isValidToken) {
url.pathname = "/admin";
return NextResponse.redirect(url);
}
}
return NextResponse.next();
}
And the structure of project:
enter image description here
Does someone get any suggestions in this case? If I am wrong, please correct me. Thank you so much.
I had similar issue. I've moved my middleware.ts file in src folder like: /src/middleware.ts and now it's getting called.
According your screenshot, it looks like your middleware.ts is out of /src folder.
Also keep in mind you can't do IO operations like calling DB in that middleware function. Still you can await promises or calling other services via fetch.
I have an Axios API call that works perfectly on a Vue page. I need to make it a stand-alone callable module to be re-used multiple times in the app. Every attempt has failed and I am not sure if it's lack of experience with a stand-alone js or something else.
Here is the working vue code.
<template>
<div>
<ul v-if="posts && posts.length">
<li v-for="post of posts">
<p><strong>{{post.resID}}</strong></p>
<p>{{post.Name}}</p>
</li>
</ul>
<ul v-if="errors && errors.length">
<li v-for="error of errors">
{{error.message}}
</li>
</ul>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: "GetMxList",
data() {
return {
posts: [],
errors: []
}
},
// Fetches posts when the component is created.
created() {
axios.get("http://localhost:8080/rest/...")
.then(response => {
// JSON responses are automatically parsed.
this.posts = response.data
})
.catch(e => {
this.errors.push(e)
})
}
}
</script>
Vue 3. Thank you for the answer. Sorry I was not clear. My goal is to create a module (like the rest.js) and then consume it in Pinia. The intent is to load once and then use the results often. Currently it works with a "static" load like the following code where the getJSONList calls a js module that returns a JSON formatted answer and puts that answer in MyList for use throughout the app. So the components just use Pinia mapping.
actions: {
async fetchList() {
const data = await getJSONList();
this.Mylist = data;
},
Many iterations. While this doesn't return aything it at least does not throw any errors...
import axios from 'axios';
export function getJSONList() {
const rest = axios.create({
baseURL: "http://localhost:8080/rest/", // better still, use env vars
});
const getPosts = async () => {
try {
return (await rest.get("http://localhost:8080/rest/")).data;
} catch (err) {
console.error(err.toJSON());
throw new Error(err.message);
}
};
return (getPosts);
}
Typically you just need to move the Axios parts into a module and leave the consumption of the data to your components.
// services/rest.js
import axios from "axios";
const rest = axios.create({
// better still, use env vars to define your URLs
baseURL: "http://localhost:8080/rest/tctresidents/v1",
});
// This is a function
export const getResidents = async () => {
try {
// the request path will be appended to the baseURL
return (await rest.get("/Residents")).data;
} catch (err) {
// see https://axios-http.com/docs/handling_errors
console.error(err.toJSON());
throw new Error(err.message);
}
};
Then in your components / store / literally anywhere...
import { getResidents } from "./path/to/services/rest";
export default {
data: () => ({ residents: [], errors: [] }),
async created() {
try {
this.residents = await getResidents();
} catch (err) {
this.errors.push(err);
}
},
};
I've been learning the mern stack from this book
I'm now on Nested Routes under React Router chapter
The web application is supposed to render this on the page.
When clicking the Select link under the Action column, the description of
an issue is displayed on the bottom part of the page.
But in my case, this thing happens:
and at the same time this error is being thrown in the console:
The only time the web application runs properly is when I downgraded the
graphql version to 0.13.2 (this is the version the book uses).
The thing is I try to use up to date versions of the project dependencies
as much as possible. There has never been much trouble as I follow the book
until I got into this.
I don't understand, why is this error being thrown when I use a more up to
date version of the graphql over the old version?
(I use graphql version 15.8.0 and apollo-server-express version 2.25.4)
I tried to modify the .jsx file that renders the description data
on the page.
async loadData() {
const { match: { params: { id } } } = this.props;
//I tried to parse the id to make it an int type before getting it into
//the graphql query
id = parseInt(id); // this is the thing that I've added
const query = `query issue($id: Int!) {
issue (id: $id) {
id description
}
}`;
const data = await graphQLFetch(query, { id });
if (data) {
this.setState({ issue: data.issue });
} else {
this.setState({ issue: {} });
}
}
This is the codes graphQLFetch function
const dateRegex = new RegExp('^\\d\\d\\d\\d-\\d\\d-\\d\\d');
function jsonDateReviver(key, value) {
if (dateRegex.test(value)) return new Date(value);
return value;
}
async function graphQLFetch(query, variables = {}) {
try {
const response = await fetch(window.ENV.UI_API_ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query, variables }),
});
const body = await response.text();
const result = JSON.parse(body, jsonDateReviver);
if (result.errors) {
const error = result.errors[0];
if (error.extensions.code === 'BAD_USER_INPUT') {
const details = error.extensions.exception.errors.join('\n');
alert(`${error.message}:\n ${details}`);
} else {
alert(`${error.extensions.code}: ${error.message}`);
}
}
return result.data;
} catch (e) {
alert(`Error in sending data to server: ${e.message}`);
return null;
}
}
When I did this, it doesn't throw any error anymore but it doesn't render
the description data on the page either.
Can someone please help me with this?? Thanks in advance...
Here is my code
import { Appwrite, Query } from "appwrite";
export default defineNuxtPlugin((nuxtApp) => {
return {
provide: {
api: () => {
const api = new Appwrite();
api
.setEndpoint(useRuntimeConfig().app.endpoint) // Your API Endpoint
.setProject(useRuntimeConfig().app.project) // Your API project ID
;
return api
}
}
}
})
//path: /plugins/demo.js
I was looking for a way around using the runtime config in the /composables directory and the **error: Nuxt instance unavailable** kept popping up, so I thought why not make that function a plugin, since it's used almost everywhere.
But the plugin appears to always return null when used with useAsyncData as shown below
//path: /pages/collections/[slug].vue
const { $api } = useNuxtApp();
const { data, pending, error, refresh } = await useAsyncData(`collectionsById-${route.params.slug}`, async () => {
const products = await $api().database.listDocuments(PRODUCTS_COLLECTION_ID)
const info = await $api().database.getDocument("62750820bc5ef93a8152", route.params.slug)
return {
info: info, /* Uncaught (in promise) TypeError: Cannot read properties of null (reading 'info') at setup ([slug].vue:20:1) */
data: products
}
})
The reason for all this is using the runtimeConfig as it is not available in the /composables. Is there a reason for the error info is throwing?
And here is my code simplified
//path: /pages/collections/[slug].vue
const { $api } = useNuxtApp();
const { data, pending, error, refresh } = await useAsyncData(`collectionsById-${route.params.slug}`, async () => {
const products = await $api().database.listDocuments(PRODUCTS_COLLECTION_ID)
// const info = await $api().database.getDocument("62750820bc5ef93a8152", route.params.slug)
return products
})
In this code the data return null
I found something about this bug I explained at end;
Component codes
async fetch(){ await this.$store.dispatch('bots/getBots') },
computed: { ...mapState('bots', ['bots']) },
Store codes
export const state = () => {
return {
bots: []
}
}
export const mutations = {
UPDATE_BOTS(state, bots) {
state.bots = bots
}
}
export const actions = {
getBots({commit}) {
this.$axios.$get('url', {headers: {uid: '12345'}})
.then(res => {
commit('UPDATE_BOTS',res.robots)
})
.catch(e => {
console.log(e)
})
}
}
Issue: When moving between pages via nuxt-link data loads perfectly but when I reload the page bots state is empty...
Found Issue:
I use nuxt-auth and I had one plugin for checking status of axios request that if it was 401 unauthorized I logout user if he was loggedIn, So status undefined error was from here but I commented the plugin codes and I got other error from nuxt-auth that causes that problem I had So I related that issue in other question u can see it here:
Nuxt-Auth Bug: Looks for autherization in any get request that has headers config
It is the expected behavior. Vuex state is kept in memory and when you reload the page it gets purged.
Instead of this state
export const state = () => {
return {
bots: []
}
}
try this
export const state = () => ({
bots: []
})