react-icons and react Router - reactjs

Context
i'm designing a navigation bar for my application and my proyect uses react-router and react-router-dom for managing routing and react-icons for icon retrieving.
Code
import React from 'react';
import { NavLink } from 'react-router-dom';
import { MdAssessment } from 'react-icons/md'
import Styles from './NavBar.module.css'
const NavBar = (props) => {
return (
<nav className={Styles.navBar}>
{navIcon}
<NavLink
activeStyle={{ color : 'red' }}
className={`${Styles.navBar__Dashboard} `}
exact to="/">
<MdAssessment />
</NavLink>
<NavLink
activeStyle={{ color: 'red' }}
className={Styles.navBar__Requests}
to="/requests">
Requests
</NavLink>
<NavLink
activeStyle={{ color: 'red' }}
className={Styles.navBar__Tasks}
to="/tasks">
Tasks
</NavLink>
</nav>
)
}
export default NavBar
Problem
I'm trying to extrapolate activeStyle functionality of NavLink to my icon.
Given that react-icons provides you with component as icons, i'm struggling with which approach should i use:
Should i wrapped in a HOC?
Should i encapsulate in a custom Hook?
Notes
I've tried with both approaches but can't get my head arround it. I've tried implementing useRef, useEffect while reading to location with useLocation hook as well.
Any suggestion for a better implementation of a generic NavIcon feature taking this context into account?

By using curly brackets you are importing the icon as a named import. So the import only works if the file contains a named export of the same name you have assigned it. See this question for more info.
According to the package documentation, this is the correct way to import an icon. Can you check to make sure the named export is the same as you have imported?

Related

NextJS Fast refresh not working as expected

I am building a website with nextjs and Chakra UI. I am using emotion to style my navigation.
The code of navigation component is as follows:
import Link from "next/link";
import { Flex, List, ListItem } from "#chakra-ui/react";
import Image from "next/image";
import styled from "#emotion/styled";
const Nav = styled.nav`
position: sticky;
top: 20px;
z-index: 2;
`;
export default function StickyNav() {
return (
<Nav>
<Flex
bg='gray.100'
justifyContent='space-between'
p='8'
borderRadius='16'
>
<Image src='/vercel.svg' alt='Vercel Logo' width={72} height={16} />
<List display='flex' ml='4'>
<ListItem mr='8'>
<Link href='#about'>
<a>About</a>
</Link>
</ListItem>
<ListItem mr='8'>
<Link href='#projects'>
<a>Projects</a>
</Link>
</ListItem>
<ListItem>
<Link href='#contact'>
<a>Contact</a>
</Link>
</ListItem>
</List>
</Flex>
</Nav>
);
}
I am having trouble with Fast refreshing. When I start the dev server, the Navigation component picks up the styles correctly
const Nav = styled.nav`
position: sticky;
top: 20px;
z-index: 2;
`;
after serving, if I try to change the top position to 10px the fast refresh doesn't reflect those changes.
The fast refresh feature is working perfectly with other components but has problem with this specific component only. I have looked through several articles but not sure what's causing this behavior.
Check filename or foldername not started with a uppercase
Fast-refresh not works :
fast-refresh works :
Also check if your import statement has right casing.
import Box from '../Components/box';
vs
import Box from '../Components/Box';
in my case, the two words filename should use dash -, rather than underscore _.
For example:
good filename: hello-world.js
bad filename: hello_world.js
As #new2cpp and DeadBoyPiotrek Stated
When Importing your headers make sure your import statements match the file names.
Navbar.js <--Example File name
import Navbar from "../components/Navbar"
Not
import Navbar from "../components/navbar"
When I made this mistake the Fast Refresh would initially load then after changing something the Fast Refresh would continue rebuilding but never finish.

#emotion/react Syntax highlighting doesn't work

I work on react project and use emotion library for styling inside .js file. Syntax highlighting in #emotion/styled works with no issue, but css function from #emotion/react causes some sort of syntax highlighting bug. Can someone tell me how to solve the issue?
import React from "react";
import { Link } from "react-router-dom";
import { css } from "#emotion/react";
import Layout from "../components/Layout";
import Heading from "../components/atoms/Heading";
import Paragraph from "../components/atoms/Paragraph";
import Button from "../components/atoms/Button";
export default function Home() {
return (
<Layout
pageTitle="Home"
css={css`
display: flex;
`}
>
<Heading>HaxBall Clone</Heading>
<Paragraph>
HaxBall clone made with react and pixi.js.
<br />
Original game:{" "}
<a href="https://haxball.com" target="_blank" rel="noreferrer">
HaxBall.com
</a>
</Paragraph>
<Button as={Link} to="/enter-user">
Play!
</Button>
</Layout>
);
}

Warning: Failed prop type: Invalid prop `tag` supplied to `NavLink`

I'm currently trying to integrate a shard-dashboard into my react app. Everything works pretty well, except that the search-navbar is scaled way too big. The console gives me the following error:
"Warning: Failed prop type: Invalid prop tag supplied to NavLink. in NavLink (at SidebarNavItem.js:8)".
The mentioned file looks as follows:
import React from "react";
import PropTypes from "prop-types";
import { NavLink as RouteNavLink } from "react-router-dom";
import { NavItem, NavLink } from "shards-react";
const SidebarNavItem = ({ item }) => (
<NavItem>
<NavLink tag={RouteNavLink} to={item.to}>
{item.htmlBefore && (
<div
className="d-inline-block item-icon-wrapper"
dangerouslySetInnerHTML={{ __html: item.htmlBefore }}
/>
)}
{item.title && <span>{item.title}</span>}
{item.htmlAfter && (
<div
className="d-inline-block item-icon-wrapper"
dangerouslySetInnerHTML={{ __html: item.htmlAfter }}
/>
)}
</NavLink>
</NavItem>
);
SidebarNavItem.propTypes = {
/**
* The item object.
*/
item: PropTypes.object
};
export default SidebarNavItem;
I've already googled this up a lot, but all related errors I've found were caused by some components which are not part of my code.
I had exactly the same problem, using the same framework.
The problem is this line:
import { NavLink as RouteNavLink } from "react-router-dom";
It seems this import syntax transforms the Component (function) into a reference, which is why you obtain an Object when logging into the console. The tag property is then wrong-typed.
A basic work-around that solves the problem:
<NavLink tag={(props) => <RouteNavLink {...props} />} to={item.to}>
your issue is that it expect Func | String but you're getting an [object Object] so you'll need to figure that out why the type is wrong

react route how to import local scss file only apply to one js file?

In one React app with React Router, for each route component, I would like to have one local scss file only apply to this file.
For below example, about.js imported about.scss, what I want to have is: about.scss override the global style in app.scss only in about.js. However, it overrode everything in the app
app.js - imported app.scss which I prefer as a global style
import React from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import "./app.scss"; // global scss
import About from "./about";
export default function App() {
return (
<>
<h1>question about scss in react route</h1>
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
</ul>
<hr />
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
</div>
</Router>
</>
);
}
function Home() {
return (
<div>
<h3 className={"myMargin"}>home</h3>
</div>
);
}
app.scss (the global style)
h3.myMargin {
margin: 10px
}
about.js
import React from "react";
import "./about.scss";
export default function About() {
return (
<div>
<h3 className={"myMargin"}>About</h3>
</div>
);
}
about.scss (I want to be a local style, however, it applied to everywhere in the app)
h3.myMargin {
margin: 100px
}
Any suggestion how to structure my style code?
The beauty (and caveat) of CSS is in the first C of its acronym —which stands for cascading— meaning there is a cascade of (fairly predictable) rules to follow.
In this case about.scss being imported later, will override your h3 from app no matter what.
1) Use a container:
import React from "react";
import "./about.scss";
export default function About() {
return (
<div className='about-page'>
<h3 className="myMargin">About</h3> // note: no need for {"myMargin"}
</div>
);
}
// about.scss
.about-page {
h3.myMargin {
margin: 10px
}
}
2) Using CSS Modules:
Another one is to use CSS Modules, enabled by default if you use a fairly recent version of create-react-app:
import React from "react";
import styles from "./About.module.scss";
export default function About() {
return (
<div>
<h3 className={styles.myMargin}>About</h3>
</div>
);
}
// About.module.scss
.myMargin {
margin: 10px
}
This will generate a unique className, so your processed code will look something like this:
<div>
<h3 class='About_myMargin_mVxOd>About</h3>
</div>
The random hash (mVxOd as an example) will allow your styles to not overwrite each other.
There are pros and cons of both methods, the biggest problem when using regular CSS/SCSS imports is that you are at the mercy of the rules of CSS: if you accidentally create a global class .error then the rules will cascade to any component and its hard to keep track. Importing Bootstrap for example, will overwrite a whole lot of CSS names that you have no idea about (until you realize your CSS is off).
Another problem is that, if a said route doesn't import a CSS file, but later on following a different path of routes does import the file, you could end up with different styling. This has happened to us a few times, so it's a must to be extra careful especially in bigger teams.
CSS Modules has a few big drawbacks, first one being that you cannot directly override a style from another CSS file just by overriding its CSS class (because of said hash). Second, you cannot access nested CSS selectors allowed by SASS.
I personally have used both for production and personal projects and both are equally great -- when used carefully.
There is a third popular option called Styled Components. It's personally not my preferred and I haven't used it much, but you can learn more abouut it on its official page. It looks like this:
const Title = styled.h3`
margin: 10px;
`
render() {
return <Title>About</Title> // creates an h3 tag
}
One last one, being CSS in JS which I haven't used enough either.

Importing Ant Design Component doesn't work

I'm shocked over this problem I'm currently having right now. All my logic literally stopped. Something started not working, without me having changed anything. I mean I even have it on production, the identical code, but locally it started not working, out of nothing. Even when I go back to previous commits, that I'm 100% sure was working, it doesn't work.
Meteor, React, Ant-Design. Please help!
The error is: ReferenceError: Layout is not defined
Code is:
import React from 'react';
import Blaze from 'meteor/gadicc:blaze-react-component';
import { Link } from 'react-router-dom';
import { Layout, Menu } from 'antd';
const { Header, Content, Footer } = Layout;
class LayoutContainer extends React.Component {
render() {
const { match, children } = this.props;
const pathname = match.location.pathname;
return (
<Layout className="layout">
<Header style={{backgroundColor: '#fff'}}>
<Menu
selectedKeys={[pathname]}
mode="horizontal"
style={{ lineHeight: '64px', float: 'right' }}
>
<Menu.Item key={'/'}>
<Link to="/">Home</Link>
</Menu.Item>
<Menu.Item key={'/create-a-gathering'}>
<Link to="/create-a-gathering">Create</Link>
</Menu.Item>
</Menu>
<div className="logo" />
<Blaze template="loginButtons" />
</Header>
<Content style={{ marginTop: 20 }}>
{children}
</Content>
<Footer style={{ textAlign: 'center' }}>
</Footer>
</Layout>
)
}
}
export default LayoutContainer;
this is a reported antd issue here Reference Error: Layout not defined
an easy way to solve this is importing layout like this
import Layout from 'antd/lib/layout'
or you can also sort it out by updating antd version to "^3.2.2" or up
I should have answered this long time ago, but here it goes:
As Afaq Ahmed Khan pointed out (that too) :
import { Layout, Menu } from 'antd/lib';
is the answer.
I guess babel in two packages conflict with each other and thus '/lib' to root '/' alias doesn't work.
That can be resolved by deleting node-modules folder then rebuilding the whole project.

Resources