Error: Invalid `paths` value returned from getStaticPaths (without any changes on files) Slug - node.js

iam recently receiving this error message without any changes to files. I deleted some products and categories via the webGUI which might cause this?
Environment is:
Frontend: React, Next.js, TypeScript & Tailwind
Backend: Laravel
Error:
> Build error occurred
Error: Invalid `paths` value returned from getStaticPaths in /category/[slug].
`paths` must be an array of strings or objects of shape { params: [key: string]: string }
at buildStaticPaths (/var/www/domain/node_modules/next/dist/build/utils.js:490:15)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at async /var/www/domain/node_modules/next/dist/build/utils.js:615:119
at async Span.traceAsyncFn (/var/www/domain/node_modules/next/dist/telemetry/trace/trace.js:60:20) {
type: 'Error'
}
Category Slug tsx content:
import Container from "#components/ui/container";
import { getLayout } from "#components/layout/layout";
import Subscription from "#components/common/subscription";
import CategoryBanner from "#containers/category-banner";
import { useRouter } from "next/router";
import CategoryProductsGrid from "#components/category/category-products-grid";
export { getStaticPaths, getStaticProps } from "#framework/ssr/category";
export default function Category() {
const { query } = useRouter();
return (
<div className="border-t-2 border-borderBottom">
<Container>
<CategoryBanner className="my-4"/>
<div className="pb-16 lg:pb-20">
<CategoryProductsGrid
classname="3xl:grid-cols-6"
categorySlug={query?.slug as string}
/>
</div>
<Subscription />
</Container>
</div>
);
}
Category.getLayout = getLayout;
SSR for category.ts:
// This function gets called at build time
export async function getStaticPaths({ locales }: GetStaticPathsContext) {
const categories = await fetchCategories({
queryKey: [API_ENDPOINTS.CATEGORIES, { limit: 100, parent: null }],
});
const paths = categories?.data?.flatMap((category: Category) =>
locales?.map((locale) => ({ params: { slug: category.slug }, locale }))
);
return {
paths,
fallback: "blocking",
};
}
Notes:
the only changes were made before the error occured via the webGUI (deleted products).
i deleted all locales on configured one locale. Maybe theres an issue. But after these changes the build ran fine for a week.
when i run the same code on my local computer with the same node etc. Versions it works. Is there any cache that must be deleted to make it work again?
Thank you in advance for any tip that could cause this. I tried alot of things but cant figure it out yet.

Related

Sometimes when I update the snapshots I got an Attribute __ngContext__

Sometimes when I update the snapshots I got an Attribute ngContext and for fix this problem I've to clean and install my node_modules to "fix" this issue.
I've to do this every time that I need to update a snapshot. I've already searched on multiple solutions and nothing worked.
snapshotSerializers: \[
'jest-preset-angular/build/serializers/no-ng-attributes',
'jest-preset-angular/build/serializers/ng-snapshot',
'jest-preset-angular/build/serializers/html-comment',
\],
Can someone help me with this, please?
Here is an image
I've updated the jest versions and also the jest-present-angular too but didn't work.
I just want to have a solution that does not makes me clean install the node_modules every time
This is indeed annoying especially because it tends to change after upgrading angular version. My snapshots are now failing as well because of this difference :-/.
- __ngContext__={[Function LRootView]}
+ __ngContext__="0"
So, having look at the jest configuration, the snapshot serializers are being loaded from 'jest-preset-angular' module.
The relevant plugin here is 'jest-preset-angular/build/serializers/ng-snapshot'. Now, they are two ways what to do to get rid of __ngContext__.
replace the plugin entirely by a modified copy
Create a copy of that file in the same directory and adapt it accordingly (line https://github.com/thymikee/jest-preset-angular/blob/40b769b8eba0b82913827793b6d9fe06d41808d9/src/serializers/ng-snapshot.ts#L69):
const attributes = Object.keys(componentInstance).filter(key => key !== '__ngContext__');
Adapt the configuration:
snapshotSerializers: [
'jest-preset-angular/build/serializers/no-ng-attributes',
'./custom-snapshot-serializer.ts',
'jest-preset-angular/build/serializers/html-comment',
],
The disadvantage of this solution is that you have to maintain the plugin although only one line has been changed.
replace the plugin by a wrapper (preferred solution)
This creates just a wrapper for the original implementation. The idea is to remove __ngContext__ before it moves on down the plugin chain. However, the logic of the original plugin is used for the fixture serialization.
import type { ComponentRef, DebugNode, Type, ɵCssSelectorList } from '#angular/core';
import type { ComponentFixture } from '#angular/core/testing';
import type { Colors } from 'pretty-format';
import { test as origTest, print as origPrint } from 'jest-preset-angular/build/serializers/ng-snapshot';
/**
* The follow interfaces are customized heavily inspired by #angular/core/core.d.ts
*/
interface ComponentDef {
selectors: ɵCssSelectorList;
}
interface IvyComponentType extends Type<unknown> {
ɵcmp: ComponentDef;
}
interface NgComponentRef extends ComponentRef<unknown> {
componentType: IvyComponentType;
_elDef: any; // eslint-disable-line #typescript-eslint/no-explicit-any
_view: any; // eslint-disable-line #typescript-eslint/no-explicit-any
}
interface NgComponentFixture extends ComponentFixture<unknown> {
componentRef: NgComponentRef;
// eslint-disable-next-line #typescript-eslint/no-explicit-any
componentInstance: Record<string, any>;
}
/**
* The following types haven't been exported by jest so temporarily we copy typings from 'pretty-format'
*/
interface PluginOptions {
edgeSpacing: string;
min: boolean;
spacing: string;
}
type Indent = (indentSpaces: string) => string;
type Printer = (elementToSerialize: unknown) => string;
export const print = (fixture: any, print: Printer, indent: Indent, opts: PluginOptions, colors: Colors): any => {
const componentInstance = (fixture as NgComponentFixture).componentInstance;
const instance = { ...componentInstance };
delete instance.__ngContext__;
const modifiedFixture = { ...fixture, componentInstance: { ...instance } };
return origPrint(modifiedFixture, print, indent, opts, colors);
};
// eslint-disable-next-line #typescript-eslint/no-explicit-any, #typescript-eslint/explicit-module-boundary-types
export const test = (val: any): boolean => {
return origTest(val);
};
The configuration is adapted the same way as before.

subscribing a http get call - why do I need to refresh my frontend page to get the data after it got altered?

So I have a web application built with angular on the frontend and node js on the backend. Im building an FAQ app where a user can add categories. See the photo below:
Those categories are stored in a pg database. When navigating to the page "Categories", I make a http call to my node js backend to get all categories from the database. My api looks like this:
app.get('/all-categories', async (req, res) => {
const result = await pool.query('select * from "Category"');
res.json(result.rows);
});
And following is my frontend, the categories.ts:
export class CategoriesComponent implements OnInit, OnDestroy {
categories: Category[] = [];
subscriptions = new Subscription();
constructor(private httpService: HttpService) { }
ngOnInit(): void {
const subscription = this.httpService.getAllCategories().subscribe(allCategories => {
this.categories = allCategories;
});
this.subscriptions.add(subscription);
}
ngOnDestroy(): void {
this.subscriptions.unsubscribe();
}
onDeleteButtonClick(categoryUUID: string) {
this.httpService.deleteCategoryByUUID(categoryUUID).pipe(
take(1)
).subscribe();
}
}
Now, whats the problem?
The problem is, when I navigate to the Categories page, all the categories are shown. But when I delete a category using the red delete button, I need to refresh the page in order to see the updated number of categories.
Why is this so? And what do I need to do to make it work?
I reckon to change the way of how you obtain the data from your service, you could subscribe to the observable in an asynchronous way with async pipe from the template, and when one category will be eliminated, you can update your observable.
on this way your .ts should be in this way:
export class CategoriesComponent implements OnInit {
categories$: Observable<Category[]> = [];
constructor(private httpService: HttpService) { }
ngOnInit(): void {
this.categories$ = this.httpService.getAllCategories();
}
async onDeleteButtonClick(categoryUUID: string) {
const deleteCategory = await this.httpService.deleteCategoryByUUID(categoryUUID).pipe(take(1))
.toPromise();
if(deleteCategory) {
this.categories$ = this.httpService.getAllCategories();
}
}
}
and your template something like this:
<div *ngIf="categories$ | async as categories">
<div *ngFor="let cat of categories">cat</div>
</div>
You can add tap operator in deleteCategoryByUUID, and filter categories:
this.categories = this.categories.filter(c => c !== c.uid);

#fullcalendar/google-calendar breaks with 'gatsby build'

#fullcalendar/google-calendar seems to try to fetch JSON during the static gatsby build. I am unsure where to start looking.
When running gatsby build on my project the build breaks with the following error:
failed Building static HTML for pages - 3.026s
error Building static HTML failed for path "/calendar/"
6431 | body = encodeParams(params);
6432 | }
> 6433 | var xhr = new XMLHttpRequest();
| ^
6434 | xhr.open(method, url, true);
6435 | if (method !== 'GET') {
6436 | xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
WebpackError: ReferenceError: XMLHttpRequest is not defined
- main.js:6433
node_modules/#fullcalendar/common/main.js:6433:1
- main.js:54
node_modules/#fullcalendar/google-calendar/main.js:54:24
- main.js:6199
node_modules/#fullcalendar/common/main.js:6199:1
- main.js:6187
node_modules/#fullcalendar/common/main.js:6187:1
- main.js:6170
node_modules/#fullcalendar/common/main.js:6170:1
- main.js:6162
node_modules/#fullcalendar/common/main.js:6162:1
- main.js:6113
node_modules/#fullcalendar/common/main.js:6113:1
- main.js:6928
node_modules/#fullcalendar/common/main.js:6928:1
- main.js:7306
node_modules/#fullcalendar/common/main.js:7306:1
The page is defined as follows:
import React from "react"
import FullCalendar from '#fullcalendar/react'
import dayGridPlugin from '#fullcalendar/daygrid'
import googleCalendarPlugin from '#fullcalendar/google-calendar';
export default class DemoApp extends React.Component {
render() {
return (
<FullCalendar
plugins={[ dayGridPlugin, googleCalendarPlugin]}
initialView="dayGridMonth"
googleCalendarApiKey='XXX'
height="100vh"
eventSources= {[
{
googleCalendarId: 'en.indian#holiday#group.v.calendar.google.com',
color: '#1f78b4'
}
]}
/>
)
}
}
I am not sure how to create an executable test case, but am very happy to receive advice. Any pointers on how I can make this work would be highly appreciated.
Using #loadable works both for build and develop versions.
import React from "react"
import loadable from '#loadable/component'
const OtherComponent = loadable(() => import('../components/calendar.js'))
function MyComponent() {
return (
<OtherComponent />
)
}
export default function Home() {
return <MyComponent />
}
Try using the following snippet in your gatsby-node.js:
exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
if (stage === "build-html") {
actions.setWebpackConfig({
module: {
rules: [
{
test: /#fullcalendar\/google-calendar/,
use: loaders.null(),
},
],
},
})
}
}
Some third-party dependencies use some global objects like window or document to make their stuff. This is perfectly valid when running gatsby develop since the code is compiled on the browser-side. However, gatsby build occurs in the server-side (your Node server) where obviously no window, because it's not even already defined yet.
That's why you need to add a null loader to the webpack's config by calling the onCreateWebpackConfig API, to avoid the dependency transpilation on the server-side.
The rule is a regular expression (that's why is between slashes) and literally, the test value matches a path in your node_modules folder to look for the dependency location, so, you must put there the exact folder name, I've assumed that is #fullcalendar/google-calendar but you have some potential folders that may create the conflict too:
import FullCalendar from '#fullcalendar/react'
import dayGridPlugin from '#fullcalendar/daygrid'
import timeGridPlugin from '#fullcalendar/timegrid'
import googleCalendarPlugin from '#fullcalendar/google-calendar';
Using #loadable/component:
import React from "react"
import loadable from '#loadable/component'
const OtherComponent = loadable(() => import('../components/calendar.js'))
function MyComponent() {
return (
<OtherComponent />
)
}
export default function Home() {
return <MyComponent />
}

Facing Issue : Warning: React.createElement: type is invalid -- expected a string

I'm using useReducer, Context and Provider in my app but I'm facing this issue please anyone faced this issue so please let me know the solution for it
Warning: React.createElement: type is invalid -- expected a string
(for built-in components) or a class/function (for composite
components) but got: %s.%s%s, undefined, You likely forgot to export
your component from the file it's defined in, or you might have mixed
up default and named imports.
Check your code at App.js:20.,
in _default (at withExpoRoot.js:20)
in RootErrorBoundary (at withExpoRoot.js:19)
in ExpoRootComponent (at renderApplication.js:35)
in RCTView (at View.js:45)
in View (at AppContainer.js:98)
in RCTView (at View.js:45)
in View (at AppContainer.js:115)
in AppContainer (at renderApplication.js:34)
- node_modules\react-native\Libraries\YellowBox\YellowBox.js:59:8 in error
- node_modules\expo\build\environment\muteWarnings.fx.js:26:24 in error
- node_modules\react\cjs\react.development.js:188:36 in warningWithoutStack
- node_modules\react\cjs\react.development.js:603:32 in warning
- node_modules\react\cjs\react.development.js:1730:14 in createElementWithValidation
* App.js:20:5 in _default
- node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:9473:27
in renderWithHooks
- node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:11994:6
in mountIndeterminateComponent
- ... 18 more stack frames from framework internals
Warning: React.createElement: type is invalid -- expected a string
(for built-in components) or a class/function (for composite
components) but got: %s.%s%s, undefined, You likely forgot to export
your component from the file it's defined in, or you might have mixed
up default and named imports.
Check your code at App.js:20.,
in _default (at withExpoRoot.js:20)
in RootErrorBoundary (at withExpoRoot.js:19)
in ExpoRootComponent (at renderApplication.js:35)
in RCTView (at View.js:45)
in View (at AppContainer.js:98)
in RCTView (at View.js:45)
in View (at AppContainer.js:115)
in AppContainer (at renderApplication.js:34)
- node_modules\react-native\Libraries\YellowBox\YellowBox.js:59:8 in error
- node_modules\expo\build\environment\muteWarnings.fx.js:26:24 in error
- node_modules\react\cjs\react.development.js:188:36 in warningWithoutStack
- node_modules\react\cjs\react.development.js:603:32 in warning
- node_modules\react\cjs\react.development.js:1730:14 in createElementWithValidation
* App.js:20:5 in _default
- node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:9473:27
in renderWithHooks
- node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:11994:6
in mountIndeterminateComponent
- ... 21 more stack frames from framework internals
Invariant Violation: Element type is invalid: expected a string (for
built-in components) or a class/function (for composite components)
but got: undefined. You likely forgot to export your component from
the file it's defined in, or you might have mixed up default and named
imports.
Check the render method of _default.
- node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:5716:10
in createFiberFromTypeAndProps
- node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:5744:4
in createFiberFromElement
- ... 22 more stack frames from framework internals
Warning: %s: Error boundaries should implement
getDerivedStateFromError(). In that method, return a state update to
display an error message or fallback UI., RootErrorBoundary
- node_modules\react-native\Libraries\YellowBox\YellowBox.js:59:8 in error
- node_modules\expo\build\environment\muteWarnings.fx.js:26:24 in error
- ... 28 more stack frames from framework internals
App.js
import React from 'react';
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import IndexScreen from './src/screens/IndexScreen';
import { Provider } from './src/context/BlogContext';
const navigator = createStackNavigator({
Index: IndexScreen
}, {
initialRouteName: 'Index',
defaultNavigationOptions: {
title: 'Blogs'
}
});
const App = createAppContainer(navigator);
export default () => {
return (
<Provider>
<App />
</Provider>
);
};
BlogContext.js
import React, { useReducer } from 'react';
export default (reducer, actions, initialState) => {
const Context = React.createContext();
const Provider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, initialState);
const boundActions = {};
for(let key in actions){
boundActions[key] = actions[key](dispatch);
}
return(
<Context.Provider value={{state, ...boundActions}}>
{children}
</Context.Provider>
);
}
return(Context, Provider);
};
You have an issue regarding BlogContext. You are not using it correctly.
You export it as default a function while in App.js, you use a named import.
BlogContext should be like this:
import React, { useReducer } from 'react';
export default (reducer, actions, initialState) => {
const Context = React.createContext();
const Provider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, initialState);
const boundActions = {};
for(let key in actions){
boundActions[key] = actions[key](dispatch);
}
return(
<Context.Provider value={{state, ...boundActions}}>
{children}
</Context.Provider>
);
}
//return an object with two keys
return {Context, Provider};
};
and App.js should use that accordingly:
import blogContext from './src/context/BlogContext';
/**
...code ...
**/
//here you create your provider by calling the function imported from BlogContext
//with the expected arguments
const { Provider } = blogContext(reducer, actions, initialState)
/**
**/
export default () => {
return (
<Provider>
<App />
</Provider>
);
};

How to configure Prism with Nuxt

How can I configure Prism to work with Nuxt? I added it as a vendor in the nuxt.config.js file:
// * Build configuration
build: {
// * You can extend webpack config here
vendor: ['axios', 'prismjs'],
extend(config, ctx) {
if (ctx.isServer) {
config.externals = [
nodeExternals({
whitelist: [/^vuetify/]
})
];
}
}
}
Then in my page in the script section I import it:
<script>
import Prism from'prismjs';
export default {
data() {
return {
post: {}
};
},
// more data...
How can I use it then? I've tried calling it in mounted but it doesn't work. No errors are returned but it doesn't change anything on site.
mounted() {
Prism.highlightAll();
}
Turned out to be working, just forgot about including css styles.

Resources