React, Bootstrap Nav - css

I'm new in React world, and stucked on beginning.
Trying to make Nav menu with react-bootstrap.Everything works fine until Nav.Item is changed.
onSelect() should change activeKey, and consequently change style on clicked Nav.Item.
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import 'bootstrap/dist/css/bootstrap.min.css';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
App.tsx:
import NavMenu from "./components/NavMenu";
const navItems: any = [
{id: 0, name: "Home", link:"home"},
{id: 1, name: "First", link:"first"},
{id: 2, name: "Second", link:"second"}
]
const App = () => {
return (
<>
<NavMenu navItems={navItems}/>
</>
);
}
export default App;
NavMenu/idnex.tsx:
import {useState} from "react";
import {Nav} from "react-bootstrap";
const NavMenu = (props: any) => {
const {navItems} = props;
const [activeNav, setActiveNav] = useState('first')
const handleClick = (eventKey: any) => setActiveNav(eventKey);
console.log(activeNav)
return (
<div>
<Nav
defaultActiveKey="home"
className="flex-column"
activeKey={activeNav}
variant="pills"
navbar={true}
onSelect={handleClick}
>
{ navItems.map((item: any) => {
const {id, link, name} = item;
return (
<Nav.Item key={id}>
<Nav.Link href={link}
eventKey={link}>
{name}
</Nav.Link>
</Nav.Item>
);
})}
</Nav>
</div>
);
}
export default NavMenu;
package.json:
{
"name": "nav-test-case",
"version": "0.1.0",
"private": true,
"dependencies": {
"#testing-library/jest-dom": "^5.11.4",
"#testing-library/react": "^11.1.0",
"#testing-library/user-event": "^12.1.10",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-scripts": "4.0.1",
"react-bootstrap": "1.4.0",
"web-vitals": "^0.2.4",
"bootstrap": "4.5.3",
"typescript": "^4.1.3"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Change is visible for one moment, and then it just rollback to default setted Nav.Item.
So it's not selected clicked Nav.Item, than the one set by default.
In Console I see change of variable from log
console.log(activeNav)
but whole page refreshes and log is reseted as well
moment before refresh
Please if someone can point me in the right direction to find out what I'm doing wrong

As far as I see it you want to have links working inside the app - but what you did is simply the way you can go to implement links to external pages.
The way to go is to use react-router-dom.
Add react-router-dom with your package manager.
Wrap your application with the BrowserRouter and define the possible Routes of your page in the Switch that defines all possible pages of your app and the according components.
<StrictMode>
<BrowserRouter>
<Switch>
<Route exact path="/" component={App} />
<Route exact path="/home" component={App} />
<Route exact path="/first" component={App} />
<Route exact path="/second" component={App} />
</Switch>
</BrowserRouter>
</StrictMode>,
Use the Link component from react-router-dom and declare your nav links as those:
<Nav.Item key={id}>
<Nav.Link as={Link} to={link} eventKey={link}>
{name}
</Nav.Link>
</Nav.Item>
That should be it.
You can see it working here: https://codesandbox.io/s/competent-cherry-8hnu9

Related

TypeError: Cannot read properties of undefined (reading 'call') sanity error

the problem that i don't know how to solve it is (TypeError: Cannot read properties of undefined (reading 'call')) basically i have no idea where it can be in the console i don't have thread only on the error page
this is what my app looks like
app/studio/[[...index]]/page.tsx
'use client'
import {NextStudio} from 'next-sanity/studio'
import config from '../../../sanity.config'
export default function StudioPage() {
// Supports the same props as `import {Studio} from 'sanity'`, `config` is required
return <NextStudio config={config} />
}
app/studio/[[...index]]/head.tsx
export {NextStudioHead} from 'next-sanity/studio/head'
import {NextStudioHead} from 'next-sanity/studio/head'
export default function CustomStudioHead() {
return (
<>
<NextStudioHead favicons={false} />
<link
rel="icon"
type="image/png"
sizes="32x32"
href="https://www.sanity.io/static/images/favicons/favicon-32x32.png"
/>
</>
)
}
app/studio/[[...index]]/head.tsx
'use client'
import config from '../../../sanity.config'
import NextStudioLoading from 'next-sanity/studio/loading'
export default function Loading() {
return <NextStudioLoading config={config} />
}
next.config.js
module.exports = {
reactStrictMode: true,
experimental:{
appDir: true
}
}
sanity.cli.ts
import {defineCliConfig} from 'sanity/cli'
export default defineCliConfig({
api: {
projectId: process.env.NEXT_PROJECT_ID,
dataset: 'production'
}
})
sanity.config.ts
import {defineCliConfig} from 'sanity/cli'
export default defineCliConfig({
api: {
projectId: process.env.NEXT_PROJECT_ID,
dataset: 'production'
}
})
package.json
{
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"#portabletext/react": "^2.0.0",
"#sanity/image-url": "^1.0.1",
"next": "latest",
"next-sanity": "^3.1.3",
"prop-types": "^15.8.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"#sanity/vision": "^3.0.0",
"sanity": "^3.0.0",
"styled-components": "^5.2.0"
},
"devDependencies": {
"#sanity/eslint-config-studio": "^2.0.1",
"#types/node": "18.11.3",
"#types/react": "18.0.21",
"#types/react-dom": "18.0.6",
"autoprefixer": "^10.4.12",
"postcss": "^8.4.18",
"tailwindcss": "^3.2.1",
"typescript": "4.8.4"
}
}
I faced the same error and solve it by installing the canary version of next 13 "npm i next#13.0.8-canary.2"

why getServerSideProps(SSR) doesn't work at vercel deploy

I am trying to deploying next js instagram clone coding.
so i used the getServerSideProps for singin with google.
it works at localhost:3000 what i want.
but after deploying this web then when i click the signin then turns out server error page.
i don't know what can i do to solve this problem.
i already downgrade firbase to 9.4.0
and i used getStaticProps(?) instead of getServerSideProps..
(if i need to use useeffect instead of getServerSideProps then please show me detail code please.... i am beginner :( )
please help me out
this is signIn code:
import {getProviders, signIn as SignIntoProvider } from "next-auth/react";
import Header from "../../components/Header";
import Image from "next/future/image";
//Brower...
function signIn({providers}){
return (
<>
<Header />
<div className="flex flex-col items-center min-h-screen py-2 mt-56 text-center">
<Image className="w-80" src="/img/스쿼드 로고.png" alt="" width={400} height={200}/>
<p className="font-xs italic">
SQUARD PROJECT - By EunSeo PARK
</p>
<div className='mt-20'>
{Object.values(providers).map((provider) => (
<div key={provider.name}>
<button className="p-3 bg-blue-500 rounded-lg text-white" onClick={() => SignIntoProvider(provider.id, {callbackUrl: "/"})}>
Sign in with {provider.name}
</button>
</div>
))}
</div>
</div>
</>
);
}
//Server side
//export async function getServerSidedProps
export async function getServerSideProps() {
const providers = await getProviders();
if (!providers) {
return {
redirect: {
destination: '/',
permanent: false,
},
}
}
return {
props: {
providers,
},
};
}
export default signIn;
this is the package.json code:
{
"name": "my-project",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"#faker-js/faker": "^7.5.0",
"#headlessui/react": "^1.7.2",
"#heroicons/react": "^1.0.6",
"#tailwindcss/forms": "^0.5.3",
"fake": "^0.2.2",
"faker": "^6.6.6",
"firebase": "^9.4.0",
"moment": "^2.29.4",
"next": "12.3.0",
"next-auth": "^4.10.3",
"next-optimized-images": "^2.6.2",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-moment": "^1.1.2",
"react-router-dom": "^6.4.1",
"recoil": "^0.7.5",
"tailwind-scrollbar-hide": "^1.1.7",
"typescript": "^4.8.4"
},
"devDependencies": {
"autoprefixer": "^10.4.11",
"eslint": "8.23.1",
"eslint-config-next": "12.3.0",
"postcss": "^8.4.16",
"tailwind-scrollbar": "^2.0.1",
"tailwindcss": "^3.1.8"
}
}
this is the next.config.js code:
/** #type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
}
const colors = require('tailwindcss/colors')
module.exports = {
images: {
domains: ['localhost', 'images.unsplash.com', 'googleusercontent.com','lh3.googleusercontent.com',
'firebasestorage.googleapis.com', 'googleapis.com','cloudflare-ipfs.com']
},
mode: 'jit',
theme: {
extend: {
colors: {
sky: colors.sky,
cyan: colors.cyan,
},
backgroundColor: ['active'],
},
},
variants: {},
plugins: [],
}

parceljs with bundle-text css import is not working

I am using Parcel to create bundles for my React Typescript application along with Shadow.
Below are my configurations,
///index.tsx file
import customCSS from "bundle-text:./assets/antd.scss"
const appContainer = document
.getElementById(config.containerId)
?.attachShadow({ mode: "open" }) as ShadowRoot
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
appContainer
)
let style = document.createElement("style")
style.textContent = customCSS
appContainer.appendChild(style)
And below is app.tsx file
import React, { Suspense } from "react"
import { BrowserRouter, Route, Routes } from "react-router-dom"
import "./app.scss"
import NotFound from "./pages/404"
import HomePage from "./pages/Home"
import Layout from "./pages/Layout"
const Application: React.FC<any> = () => {
return (
<Suspense fallback={<div>Loading...</div>}>
<BrowserRouter basename="/">
<Routes>
<Route path="*" element={<NotFound />} />
<Route element={<Layout />}>
<Route index element={<HomePage />} />
</Route>
</Routes>
</BrowserRouter>
</Suspense>
)
}
below is assets/antd.scss file
#import "npm:antd/dist/antd.min.css";
I have added declaration.d.ts file for declaring bundle-text:.
declare module "bundle-text:*" {
const value: string
export default value
}
ISSUE:
Now issue is that bundle-text is working fine but normal css import is not working. If I comment the bundle-text, then regular CSS import is working fine.
EXPECTED:
Both bundle-text and regular CSS import should work properly.
Below is my package.json dependencies,
"dependencies": {
"antd": "^4.18.8",
"history": "^5.2.0",
"i18next": "^21.6.11",
"parcel": "2.3.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-i18next": "^11.15.4",
"react-router-dom": "^6.2.1",
"typescript": "4.5.5"
},
"devDependencies": {
"#csstools/normalize.css": "^12.0.0",
"#parcel/transformer-inline-string": "2.3.2",
"#parcel/transformer-sass": "^2.3.2",
"#trivago/prettier-plugin-sort-imports": "^3.2.0",
"#types/react": "^17.0.39",
"#types/react-dom": "^17.0.11",
"#typescript-eslint/eslint-plugin": "^5.12.0",
"#typescript-eslint/parser": "^5.12.0",
"autoprefixer": "^10.4.2",
"eslint": "^8.9.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "^27.5.1",
"node-sass": "^7.0.1",
"parcel": "^2.3.2",
"postcss": "^8.4.6",
"postcss-modules": "^4.3.0",
"prettier": "^2.5.1",
"process": "^0.11.10",
"sass": "^1.49.8",
"typescript": "^4.5.5"
},
Is it something which I am missing here?
Update:
I have updated added my code to the sandbox environment -
parcel-shadowDOM-react-app
Unfortunately, I think this a bug in parcel - I created a simplified reproduction here and filed this github issue.
As a workaround that you could use before we fix this, I've found that if you do all your css imports through the bundle-text pipeline, parcel will keep it straight. I.e. you'll want to find places in your app where you do global css imports (e.g. import "./styles.css") with this:
import stylesString from "bundle-text:./styles.css"
let styleElement = document.createElement("style");
styleElement.textContent = stylesString ;
shadowRoot.appendChild(styleElement);
You need use sass-to-string package to transform your scss in css first

How to fix "TypeError: rule.assign is not a function" when trying to import ReactToastify.css

I can import { ToastContainer } from 'react-toastify with no problems, but when I try to
import 'react-toastify/dist/ReactToastify.css';, I get an error:
./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[2].oneOf[7].use[1]!./node_modules/next/dist/build/webpack/loaders/postcss-loader/src/index.js??ruleSet[1].rules[2].oneOf[7].use[2]!./node_modules/react-toastify/dist/ReactToastify.css
TypeError: rule.assign is not a function
I'm using next.js and tailwind css with 'jit' mode enabled.
_app.js:
import 'tailwindcss/tailwind.css';
import '../public/css/syles.css';
import NavBar from '../components/NavBar';
// dynamic(
// () =>
// import('!style-loader!css-loader!react-toastify/dist/ReactToastify.css'),
// { ssr: false } <== tried this as a potential fix, but didn't work.
// );
// import dynamic from 'next/dynamic';
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
function MyApp({ Component, pageProps }) {
return (
<>
<ToastContainer position='top-center' />
<NavBar />
<Component {...pageProps} />;
</>
);
}
export default MyApp;
package.json:
{
"name": "client",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "node server.js",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"#headlessui/react": "^1.4.2",
"#heroicons/react": "^1.0.5",
"#tailwindcss/line-clamp": "^0.2.2",
"axios": "^0.24.0",
"bootstrap": "^5.1.3",
"express": "^4.17.1",
"heroicons": "^1.0.5",
"http-proxy-middleware": "^2.0.1",
"next": "^12.0.7",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-toastify": "^8.1.0"
},
"devDependencies": {
"autoprefixer": "^10.4.0",
"postcss": "^8.4.3",
"postcss-preset-env": "^7.0.1",
"tailwindcss": "^2.2.19"
}
}
Any suggestions would be appreciated. Thanks.
Ok, so I solved it by { injectStyle } and executing in useEffect().
I referred to this page: https://fkhadra.github.io/react-toastify/how-to-style/#inject-style-on-demand
_app.js:
import 'tailwindcss/tailwind.css';
import '../public/css/syles.css';
import NavBar from '../components/NavBar';
import { useEffect } from 'react';
import { ToastContainer } from 'react-toastify';
import { injectStyle } from 'react-toastify/dist/inject-style';
function MyApp({ Component, pageProps }) {
useEffect(() => {
injectStyle();
}, []);
return (
<>
<ToastContainer position='top-center' />
<NavBar />
<Component {...pageProps} />;
</>
);
}
export default MyApp;

Vuetify CSS missing when i build for production

We purchased a web app written in Vue from someone and we developing to change/improve it. One thing we added was Vuetify so we can use the Vuetify elements and everything has been working great while in development mode, but when we build for production the CSS for Vuetify elements is missing.
I have searched for this online already and have already tried what everybody is suggesting without any luck.
Anybody has an idea of what could be wrong and why npm run build would be missing some of the CSS?
What's weird is that all the UI functionality for Vue elements is working perfectly, just the CSS is missing.
Please see code samples below.
main.js:
import '#fortawesome/fontawesome-free/css/all.css'
import Vue from "vue";
import App from "./App.vue";
import VueMoment from "vue-moment";
import VueAnalytics from "vue-analytics";
import VueMeta from "vue-meta";
import { library } from "#fortawesome/fontawesome-svg-core";
import {
faCoffee,
faPlusCircle,
faChartLine,
faChevronDown,
faMobile,
faEnvelope,
faClock,
faUsers,
faPaperPlane,
faCheckCircle,
faCheck,
faLeaf,
} from "#fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "#fortawesome/vue-fontawesome";
import axios from "axios";
import router from "./router";
import store from "./store";
import vuetify from './plugins/vuetify';
import Vuetify from 'vuetify/lib'
library.add([
faCoffee,
faPlusCircle,
faChartLine,
faChevronDown,
faMobile,
faEnvelope,
faClock,
faUsers,
faPaperPlane,
faCheckCircle,
faCheck,
faLeaf,
]);
Vue.use(VueAnalytics, {
id: "xxx",
router,
});
Vue.use(VueMoment);
Vue.use(VueMeta);
Vue.component("font-awesome-icon", FontAwesomeIcon);
Vue.use(Vuetify)
axios.interceptors.response.use(undefined, async function (error) {
if (error.response.status === 401) {
await store.dispatch("auth/logout");
router.push("/login");
}
return Promise.reject(error);
});
// Plugins
// ...
// Sass file
require("./assets/styles/main.css");
Vue.config.productionTip = false;
new Vue({
router,
store,
vuetify,
render: (h) => h(App)
}).$mount("#app");
App.vue:
<template>
<v-app>
<v-main>
<router-view/>
</v-main>
</v-app>
</template>
<style>
.text-white {
color: #fff !important;
}
.text-gray-600 {
color: #757575 !important;
}
.font-semibold, .text-gray-700 {
color: #616161 !important;
}
</style>
package.json:
{
"name": "reviewgrower-spa",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"deploy": "git push dokku master"
},
"dependencies": {
"#fortawesome/fontawesome-svg-core": "^1.2.25",
"#fortawesome/free-solid-svg-icons": "^5.11.2",
"#fortawesome/vue-fontawesome": "^0.1.8",
"#fullhuman/postcss-purgecss": "^1.3.0",
"axios": "^0.19.0",
"chart.js": "^2.9.4",
"core-js": "^2.6.10",
"i": "^0.3.6",
"jquery": "^3.5.1",
"npm": "^6.13.0",
"tailwindcss-spinner": "^0.2.0",
"tailwindcss-toggle": "github:TowelSoftware/tailwindcss-toggle",
"url-parse": "^1.4.7",
"vue": "^2.6.10",
"vue-analytics": "^5.17.2",
"vue-chartjs": "^3.5.1",
"vue-click-outside": "^1.0.7",
"vue-clickaway": "^2.2.2",
"vue-feather-icons": "^4.22.0",
"vue-js-toggle-button": "^1.3.3",
"vue-meta": "^1.6.0",
"vue-moment": "^4.0.0",
"vue-router": "^3.1.3",
"vue-stripe-elements-plus": "^0.2.10",
"vuetify": "^2.4.0",
"vuex": "^3.0.1",
"vuex-persist": "^2.1.1"
},
"devDependencies": {
"#fortawesome/fontawesome-free": "^5.15.2",
"#vue/cli-plugin-babel": "^3.12.1",
"#vue/cli-plugin-eslint": "^3.12.1",
"#vue/cli-service": "^3.12.1",
"babel-eslint": "^10.0.3",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.2.3",
"sass": "^1.32.0",
"sass-loader": "^7.1.0",
"tailwindcss": "^1.1.3",
"vue-cli-plugin-vuetify": "~2.1.0",
"vue-template-compiler": "^2.5.21",
"vuetify-loader": "^1.7.0"
}
}
It's a little tough to understand what is missing where. If you think that is just missing then please try adding css onto the HTML file from the cdn and check the working.
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
I see that you are using webpack to compile the code. So, this could be also something related to webpack configuration. In your webpack rules do you have rules for css and scss. Because vuetify files are in scss.
My webpack configuration is as below when I do these type of circus.
--webpack.config.js--
const path = require("path");
const VuetifyLoaderPlugin = require("vuetify-loader/lib/plugin");
const { VueLoaderPlugin } = require("vue-loader");
module.exports = {
watch: true,
entry: {
main: 'main.js'
},
module: {
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.vue$/,
use: "vue-loader",
},
{
test: /\.s(c|a)ss$/,
use: [
"vue-style-loader",
"css-loader",
{
loader: "sass-loader",
// Requires sass-loader#^8.0.0
// options: {
// implementation: require('sass'),
// sassOptions: {
// fiber: require('fibers'),
// indentedSyntax: true // optional
// },
// },
},
],
},
],
},
plugins: [
new VueLoaderPlugin(),
new VuetifyLoaderPlugin({
/**
* This function will be called for every tag used in each vue component
* It should return an array, the first element will be inserted into the
* components array, the second should be a corresponding import
*
* originalTag - the tag as it was originally used in the template
* kebabTag - the tag normalised to kebab-case
* camelTag - the tag normalised to PascalCase
* path - a relative path to the current .vue file
* component - a parsed representation of the current component
*/
match(originalTag, { kebabTag, camelTag, path, component }) {
if (kebabTag.startsWith("core-")) {
return [
camelTag,
`import ${camelTag} from '#/components/core/${camelTag.substring(
4
)}.vue'`,
];
}
},
}),
],
}
Check your postcss.config.js, see if it has something to do with the purgecss.
You have to config the whitelist to ignore the vuetify styles.
Here is a sample for your reference:
const autoprefixer = require("autoprefixer");
const postcssImport = require("postcss-import");
const purgecss = require("#fullhuman/postcss-purgecss");
const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV);
let plugins = [];
if (IS_PROD) {
plugins.push(postcssImport);
plugins.push(
purgecss({
content: [
"./src/**/*.vue",
"./public/**/*.html",
`./node_modules/vuetify/src/**/*.ts`,
`./node_modules/vuetify/dist/vuetify.css`
],
defaultExtractor (content) {
const contentWithoutStyleBlocks = content.replace(/<style[^]+?<\/style>/gi, '')
return contentWithoutStyleBlocks.match(/[A-Za-z0-9-_/:]*[A-Za-z0-9-_/]+/g) || []
},
safelist: [ /-(leave|enter|appear)(|-(to|from|active))$/, /^(?!(|.*?:)cursor-move).+-move$/, /^router-link(|-exact)-active$/, /data-v-.*/ ],
whitelist: [
'container',
'row',
'spacer',
'aos-animate',
'col',
'[type=button]',
'v-application p',
],
whitelistPatterns: [
/^v-.*/,
/^col-.*/,
/^theme-.*/,
/^rounded-.*/,
/^data-aos-.*/,
/^(red|grey)--text$/,
/^text--darken-[1-4]$/,
/^text--lighten-[1-4]$/
],
whitelistPatternsChildren: [
/^post-content/,
/^v-input/,
/^swiper-.*/,
/^pswp.*/,
/^v-text-field.*/,
/^v-progress-linear/
]
})
);
}
module.exports = {
plugins:[
require('cssnano')({
preset: 'default'
}),
require('postcss-pxtorem')({
remUnit:15, //每个rem对应的px值
threeVersion:true
}),
...plugins,autoprefixer
]
}``
You are simply missing an include in your main.js (see vuetify docs):
import 'vuetify/dist/vuetify.min.css'
This will ensure that webpack includes the vuetify styles in the bundled CSS for production. This fixed the same issue for me (i.e. it worked locally but not in production).

Resources