Error when adding Headless-ui in a Deno+Fresh Project - deno

I have a Deno+Fresh project and when adding headlessui to my Fresh projec I get the following error:
TypeError: Cannot read properties of undefined (reading '__H')
I read the following discussion that apparently addresses my issue... https://github.com/denoland/fresh/discussions/606
But I can not make it work.
To debug the issue I created a demo project (https://github.com/datracka/test-headlessui2)
It is just a new fresh project created with deno run -A -r https://fresh.deno.dev my-project where I just added a new island MySwitch, importing directly the headlessui module as described in the github discussion thread.
import { Switch } from "https://esm.sh/#headlessui/react#1.6.6?alias=react:preact/compat,react-dom:preact/compat,#types/react:preact/compat&deps=preact#10.10.0";
import { useState } from "preact/hooks";
import { tw } from "twind";
export default function () {
const [checked, setChecked] = useState(false);
const toggleChecked = () => setChecked(!checked);
return (
<Switch
checked={checked}
onChange={toggleChecked}
class={tw`${
checked ? "bg-blue-600" : "bg-gray-200"
} relative inline-flex h-6 w-11 items-center rounded-full`}
>
<span class={tw`sr-only`}>Enable notifications</span>
<span
class={tw`${
checked ? "translate-x-6" : "translate-x-1"
} inline-block h-4 w-4 transform rounded-full bg-white`}
/>
</Switch>
);
}
It fires the error above when running the project with deno task start.
What am I missing?
Thanks for your help and time!

Found the issue
The import was fine:
import { Switch } from "https://esm.sh/#headlessui/react#1.6.6?alias=react:preact/compat,react-dom:preact/compat,#types/react:preact/compat&deps=preact#10.10.0";
Only you have to have in consideration the current version of preact in your Fresh project. Otherwise they collide and therefore raise the error above.
In my case the current version was 10.11.0 and not 10.10.0
I hope it helps somebody.

Related

Lazy loading fontawesome icons in vue3 + vite not working in DEV

In my vue3+vite project I'm using the official fontawesome vue3 package (see use with vue).
In order to enable tree-shaking you need to statically load the necessary icons (or possibly all of them) in advance using library.add. See for instance the following App.vue
<script setup>
import { ref, computed } from "vue";
import { library } from "#fortawesome/fontawesome-svg-core";
import { FontAwesomeIcon } from "#fortawesome/vue-fontawesome";
import { definition } from "#fortawesome/free-solid-svg-icons/faTruck";
library.add(definition);
const icon = ref("");
const showIcon = () => { icon.value = `fa-solid fa-truck`; };
</script>
<template>
<button #click="showIcon">Show Truck Icon</button>
<div v-if="icon">
<font-awesome-icon :icon="icon" />
</div>
</template>
here we statically load the truck icon and when you click the button the icon shows up.
What I was trying to do is loading the icons on demand (in this case, only when the button is clicked), using the following code:
<script setup>
import { ref, computed } from "vue";
import { library } from "#fortawesome/fontawesome-svg-core";
import { FontAwesomeIcon } from "#fortawesome/vue-fontawesome";
const modules = import.meta.glob(
"../node_modules/#fortawesome/free-solid-svg-icons/faTruck.js",
{ eager: false, import: "definition" }
);
const icon = ref("");
const showIcon = () => {
Object.values(modules)[0]().then((elem) => {
library.add(elem);
icon.value = `fa-solid fa-truck`;
});
};
</script>
<template>
<button #click="showIcon">Show Truck Icon</button>
<div v-if="icon">
<font-awesome-icon :icon="icon" />
</div>
</template>
But this doesn't work in "develpment" (npm run dev):
it makes a call to http://localhost:5173/node_modules/#fortawesome/free-solid-svg-icons/faTruck.js
then raises an error: Uncaught (in promise) ReferenceError: exports is not defined
while it works fine when the bundle is built (npm run build then for example serve the dist folder with http-server)
I suspect the problem is related to the fact that in development mode faTruck.js module is used "as is", while it is transpiled in the build phase.
Is there a solution?
NOTE:
The example contains only the "truck" because is over-simplified, but actually any icon should be loaded; i.e. the actual path in import.meta.glob should be ../node_modules/#fortawesome/free-solid-svg-icons/fa*.js
Full steps to reproduce the issue:
npm create vue#3 # accepts all defaults
cd vue-project
npm i #fortawesome/fontawesome-svg-core #fortawesome/free-solid-svg-icons #fortawesome/vue-fontawesome
# replace src/App.vue with the one indicated above
# run in dev with
npm run dev
# or build for prod and then expose using http-server
npm run build
npx http-server dist
Explaination
According to the Vite pre-bundling docs:
Vite's dev serves all code as native ESM. Therefore, Vite must convert dependencies that are shipped as CommonJS or UMD into ESM first
But when you use glob import with dynamic variables, your modules will not be pre-bundled. Since #fortawesome/free-solid-svg-icons/faTruck.js is a CommonJS file, it can not be used directly in ESM. And you are right that Vite does transform the module on production build, so it works well on production.
You may think about the optimizeDeps.include option but unfortunately, it does not help in this situation. Even if you add your module to the include list, Vite does pre-bundle your module but it will not use that pre-bundled file for your dynamic import. It still uses the file in node_modules/#fortawesome/free-solid-svg-icons/ folder.
I'm afraid that there is no straightforward solution to your problem. See this issue
Workaround
Just make it work differently on dev and prod.
const showIcon = async () => {
let x = 'faTruck'
let definition
if (import.meta.env.PROD) {
const iconModule = await import(
`../node_modules/#fortawesome/free-solid-svg-icons/${x}.js`
)
definition = iconModule.definition
} else {
const iconModule = await import(`#fortawesome/free-solid-svg-icons`)
definition = iconModule[x]
}
library.add(definition)
icon.value = `fa-solid fa-truck`
}
With this code, you still have the benefit of lazy loading on production and a smooth dev server to work
Another approach
Hard-coding your import list like so:
const showIcon = async (iconName) => {
const listImport = {
faTruck: () => import(`#fortawesome/free-solid-svg-icons/faTruck`),
faWarning: () => import(`#fortawesome/free-solid-svg-icons/faWarning`),
}
const iconModule = await listImport[iconName]()
console.log('iconModule', iconModule)
library.add(iconModule.definition)
}
But I bet you have hundreds of icons in your list so it hardly is an option

Next js and Next Auth overlapping react declarations

I am running Next js and Next Auth in multiple project, and all of a sudden all of them decided to crash with the same error.
Module parse failed: Identifier '_react' has already been declared (14:6)
File was processed with these loaders:
* ./node_modules/next/dist/build/webpack/loaders/next-swc-loader.js
You may need an additional loader to handle the result of these loaders.
| const _material = require("#mui/material");
| const _xDataGrid = require("#mui/x-data-grid");
> const _react = require("next-auth/react");
| const _reportTable = /*#__PURE__*/
a simple example that crashes looks like this...
As you can see from the example below. I am not importing react twice.
import React from "react";
import { Box } from "#mui/material";
import { DataGrid, GridColDef, GridRowsProp } from "#mui/x-data-grid";
import { getSession } from "next-auth/react";
import ReportTable from "../src/components/ReportTable";
export default function Home() {
const findSession = () => {
const session = getSession();
console.log(session);
return session;
};
return (
<Box>
<ReportTable title="Price Books">
<DataGrid
sx={{ border: "0" }}
rows={rows}
columns={columns}
headerHeight={40}
/>
</ReportTable>
</Box>
);
}
If I remove the getSession import at the top everything runs fine. The other developers on my team can run these project just fine, so I believe it's an environmental issue on my side.
Has anyone else run into this issue?
I have built the project and it works fine. The errors only occur in my dev environment.
I also cloned the repo on my personal machine and it worked fine there as well.
The problem was with a new plugin that came out today, "Code Ninja". If you are facing this issue, disable that VSCode extension.

Nextjs v 13 - TypeError: Cannot read properties of null (reading 'length') [duplicate]

This question already has answers here:
NextJS TypeError: Cannot read properties of null (reading 'length')
(4 answers)
Closed 3 months ago.
I am trying to learn how to make a nextjs app with this egghead tutorial. I am stuck on lesson 4 which shows how to read data from a supabase db.
I think the issue might have something to do with a change in nextjs v 13. This post has a suggestion, which is to change the Home function into a const with an arrow in it. I tried it as follows but still can't get the code to work as demonstrated.
import { supabase } from '../utils/supabase'
const Home = ({lessons}) => {
return (
<div className="flex min-h-screen flex-col items-center justify-center py-2">
{lessons.map( lesson => (
<p key={lesson.id}>{lesson.title}</p>
))}
</div>
)
}
export default Home;
export const getStaticProps = async () => {
const { data: lessons } = await supabase.from('lesson').select('*')
return { props: { lessons } }
}
My error message is in the browser is:
Error: Failed to fetch update manifest Internal Server Error at
http://localhost:3000/_next/static/chunks/webpack.js?ts=1668894571923:1188:37
My error message in the terminal is:
TypeError: Cannot read properties of null (reading 'length') at eval
(webpack-internal:///./node_modules/next/dist/client/dev/error-overlay/hot-dev-client.js:262:55)
Does anyone know what the changes are that are required in order to update an outdated nextjs to work with next v13? I can't make sense of the nextjs update documentation.
This looks like a bug caused by v13.0.3 of Next.js. I opened a PR (https://github.com/vercel/next.js/pull/43145) with a potential fix.
In the meantime, you may be able to get around this by downgrading to 13.0.2.

Why is Vercel failing to build my Next.js tsx app?

When I run npm run build and npm start on my local machine it deploys perfectly to localhost but when I try to deploy the very same code to Vercel I get the following error:
08:28:16 Failed to compile.
08:28:16 ./pages/index.tsx:5:20
08:28:16 Type error: Cannot find module '../components/layout' or its corresponding type declarations.
It definitely seems like an issue with the Layout component, I switched around the order of the important and it always fails when trying to load the Layout component. Here's the code for the component:
import Alert from "./alert";
import Footer from "./footer";
import Meta from "./meta";
type Props = {
preview?: boolean;
children: React.ReactNode;
};
const Layout = ({ preview, children }: Props) => {
return (
<>
<Meta />
<div className="min-h-screen">
<Alert preview={preview} />
<main>{children}</main>
</div>
<Footer />
</>
);
};
export default Layout;
index.tsx line 5 looks like this import Layout from "../components/layout"; and I've confirmed that that is the correct path for the Layout component.
are you sure the file name is layout.tsx not Layout.tsx :-)
I went through the same thing.
Fix layout.tsx to Layout.tsx
The file name and component name must be the same.

React-tooltip and Next.js SSR issue

I use the react-tooltip library in my Next.js app.
I noticed that every time I refresh a website while visiting a page that uses the tooltip I get an error:
react-dom.development.js:88 Warning: Prop `dangerouslySetInnerHTML` did not match.
CSS classes are different on the client and on the server
The weird part is I do not get that error while navigating from a random page to a page that uses the react-tooltip.
The tooltip related code:
<StyledPopularityTooltipIcon src="/icons/tooltip.svg" alt="question mark" data-tip="hello world" />
<ReactTooltip
effect="solid"
className="tooltip"
backgroundColor="#F0F0F0"
arrowColor="#F0F0F0"
clickable={true}
/>
I had the same issue, I had to use state to detect when component has been mounted, and show the tooltip only after that.
P.S. You don't see the error when navigating, because the page is not rendered on server when you navigate, it's all front-end :)
In case you are using any server-side rendering (like Next.js) - you will need to make sure your component is mounted first before showing the react-tooltip.
I fixed this by using the following:
import React, { useEffect, useState } from 'react';
const [isMounted,setIsMounted] = useState(false); // Need this for the react-tooltip
useEffect(() => {
setIsMounted(true);
},[]);
return (<div>
{isMounted && <ReactTooltip id={"mytip"} effect={"solid"} />}
<span data-tip={"Tip Here"} data-for={"mytip"}>Hover me</span>
</div>)
You should wrap your JSX in the following component:
import React, { useEffect, useState } from 'react';
const NoSsr = ({ children }): JSX.Element => {
const [isMounted, setMount] = useState(false);
useEffect(() => {
setMount(true);
}, []);
return <>{isMounted ? children : null}</>;
};
export default NoSsr;
Like this:
<NoSsr>
<YourJSX />
</NoSsr>
If you are working with NEXTJS this might be a good approach, you can check the documentation here as well, also if you are working with data-event, globalEventOff or any other prop and is not hiding or not working in your localhost, this only occurs in Development Strict Mode. ReactTooltip works fine in Production code with React 18. So you can set reactStrictMode : false, in your next.config.js to test it locally and then set it back to true, hope this helps :) info reference here
import dynamic from 'next/dynamic'
const ReactTooltip = dynamic(() => import('react-tooltip'), { ssr : false });
function Home() {
return (
<div>
<Button
data-tip
data-event="click focus"
data-for="toolTip"
onClick={():void => ()}
/>
<ReactTooltip id="toolTip" globalEventOff="click"/>
</div>
)
}
export default Home

Resources