My post/explanation of my problem is kind of long so I'll post the question at the top as well as at the bottom:
how can I use react-bootstrap with pug syntax when there is dot notation built into the react-bootstrap navbar?
=====================================================================
I'm following along a video tutorial to learn how to use React Bootstrap. Unlike the tutorial, however, I'm using pug-as-jsx-loader so that I can write my react components using pug syntax. Everything was working fine until we got to the navbar portion.
Here is what the code looks like:
return (
<Navbar default collapseOnSelect>
<Navbar.Header>
<Navbar.Brand>
<Link to='/'> Teeessst </Link>
</Navbar.Brand>
<Navbar.Toggle />
</Navbar.Header>
<Navbar.Collapse>
<Nav pullRight>
<NavItem eventKey={1} componentClass={Link} href='/' to='/'>
Home
</NavItem>
<NavItem eventKey={2} componentClass={Link} href='/about' to='/about'>
About
</NavItem>
<NavItem eventKey={3} componentClass={Link} href='/news' to='/news'>
News
</NavItem>
</Nav>
</Navbar.Collapse>
</Navbar>
)
And here is what the code would look like if I was able to use pug syntax:
return pug`
Navbar(default, collapseOnSelect)
Navbar.Header
Navbar.Brand
Link(to='/') Ayyy
Navbar.Toggle
Navbar.Collapse
Nav(pullright)
NavItem(eventKey='{1}' componentClass='{Link}' to='/') Home
NavItem(eventKey='{2}' componentClass='{Link}' to='/about') About
NavItem(eventKey='{3}' componentClass='{Link}' to='/news') News
`
Now, the bottom example still rendered a navbar to the page, but it was 'broken' in the sense that the buttons weren't in the right place, and didn't do anything when you click them. The top example DOES work, but I'd like to be able to use the bottom example instead.
I believe the problem is because a dot in pug syntax indicates a classname. So for Navbar.Header pug thinks that should be Navbar class='Header'
I thought I could try to fix this problem by changing some of the source code in react-bootstrap. I found that in the Navbar.js file from the bootstrap code there is this snippet at the bottom:
UncontrollableNavbar.Brand = NavbarBrand;
UncontrollableNavbar.Header = NavbarHeader;
UncontrollableNavbar.Toggle = NavbarToggle;
UncontrollableNavbar.Collapse = NavbarCollapse;
export default bsStyles([Style.DEFAULT, Style.INVERSE], Style.DEFAULT,UncontrollableNavbar);
So it seemed to me that it was exporting an object called UncontrollableNavbar which had properties which were simply from other files. I looked in the directory, and it had all of those files there, so I thought I could change my code from this:
import {Navbar, Nav, NavItem} from 'react-bootstrap'
// skip some lines
<Navbar.Header>
// skip some lines
To this:
import {Navbar, Nav, NavItem, NavbarHeader} from 'react-bootstrap'
// skip some lines
<NavbarHeader>
// skip some lines
Webpack and babel are able to load this just fine, however the page does not show anything because there's this error in the Chrome console: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.
I'm assuming this error is something to do with the state of the Navbar? Like the reason it uses dot notation is maybe because it needs to pass data to the children, but if I use a seperate tag instead of Maybe it's not able to pass the data properly, and crashes the app?
Basically, my question is, how can I use react-bootstrap with pug syntax when there is dot notation built into the react-bootstrap navbar?
You can have a reference for each subcomponent:
import {Navbar, Nav, NavItem} from 'react-bootstrap'
const Header = Navbar.Header;
...other consts...
return pug`
Navbar(default, collapseOnSelect)
Header
Brand
Link(to='/') Ayyy
Toggle
Related
I am building a Next.js app where some of the pages have in-page-routes one them. To accommodate this, I am using a catch-all (i.e. [[...slug]]) and handling the routes on that page itself. My folder structure looks like this:
While these routes work as expected, I am running into an issue where if I include an "as" prop to the Next.js Link component when referencing one of these catch-all pages, the href breaks, and the page refreshes to the "as" url. Here is my code:
import { useRouter } from "next/router";
import Link from "next/link";
export default function Header() {
const router = useRouter();
return (
<header>
<nav>
<ul>
<NavItem link="/">Logo</NavItem>
<NavItem link="/games/crash">Link Text</NavItem>
<NavItem link="/games/double">Link Text</NavItem>
<NavItem link="/games/mines">Link Text</NavItem>
<NavItem link="/profile">
<Profile />
</NavItem>
<NavItem link={router.asPath} as="/deposit">
<RoundPurpleButton />
</NavItem>
<MoreButton />
</ul>
</nav>
</header>
);
}
function NavItem({ children, link, as }) {
return (
<li>
<Link href={link} as={as}>
<a> {children}</a>
</Link>
</li>
);
}
All header elements link to their own page except the Purple Round button. For reasons (modal functionality) it links to the current page but displays a different url. I am using dynamic link building, passing an href and an as prop to the Next.js Link component. This is where I am getting strange behavior.
If I pass just a link everything works fine. You can see from the below picture each header and the link that it routes to (above the header element). In this scenario each header element, when clicked, takes you to the specified link.
The moment I add an "as" prop however, the round purple button displays the correct "link" and "as" attributes but when you click on it you see this message in the console: GET http://localhost:3001/_next/static/chunks/pages/games/double.js net::ERR_ABORTED 404 (Not Found) then the page refreshes to the "as" url.
I believe this issue has something to do with the Next.js catch-all links because I do not get this issue on statically typed link like "/", it's only on the catch-all links like "profile/[[...profile]]."
Does anyone have any ideas on how to fix this issue or how to properly structure the routes to allow for this functionality?
as is supposed to be a component (or a standard HTML component name like "a"). Currently, you're passing a path there. You may want to leave your as prop as as={as}
Related to this question, whose top answers no longer work. By default, the NavDropdown only appears when clicked on, however I need this dropdown to display on hover. I struggled loading 'React-Bootstrap' into stackoverflow to create a reproducible example, however here is a basic Navbar using react-bootstrap, that features my attempt to display the dropdown on hover:
const [isStatsOpen, setIsStatsOpen] = useState(true);
<Navbar>
<Navbar.Brand>
<Link to='/'>
<img alt='company logo' src={My Logo} />
</Link>
</Navbar.Brand>
<Navbar.Toggle aria-controls='basic-navbar-nav' />
<Navbar.Collapse id='basic-navbar-nav'>
<Nav className='mr-auto'>
<NavDropdown title='Statistics'
onMouseEnter={() => setIsStatsOpen(true)}
onMouseLeave={() => setIsStatsOpen(false)}
open={isStatsOpen}
>
<NavDropdown.Item as={Link} to='/stats/'> Stats 1</NavDropdown.Item>
<NavDropdown.Item as={Link} to='/stats2/'>Stats 2</NavDropdown.Item>
</NavDropdown>
</Nav>
<Nav className='ml-auto'>
<DivisionSelect />
<AppSelect />
</Nav>
</Navbar.Collapse >
</Navbar >
From the linked post above, there were 2 responses with 10+ votes, however neither of these solutions work. As it pointed out in one of the comments: This doesn't work in newer versions, the dropdown isn't rendered until it's first click. You'd need to trigger the onclick before you could control via css.
After inspecting the page, I can confirm that this person is correct - there is no menu for which to display until after the NavDropdown has been clicked upon. Once clicked, the menu is there, and then the solutions from this other post do work. Given this as the case, how can I resolve this issue? Is it possible for my react component to automatically "click" the Navdropdowns on load, that way the menus will appear on hover?
Thanks!
Does this help you? Old good vanilla javascript.
I added an id at NavDropdown and called the old, classic document.getElementById method and then triggered the click event.
useEffect(() => {
document.getElementById("test").click();
}, []);
<NavDropdown
id="test"
title="Statistics"
https://codesandbox.io/s/react-bootstrap-demo-z36c5
In this link to the earlier version of the question, the highly voted answer that starts with export class Nav extends React.Component { does work, so long as the open prop is updated to show.
I'm using Reactstrap to style my React/Redux app, and I'm having some trouble aligning things as I'd like; I know I'm giving up easy access to finer-grained control using the library, but I suspect there's a way to do what I want.
So, I have a basic Navbar at the top of my content (I compressed the Nav options).
<Navbar light expand={ "lg" }>
<NavbarBrand>Redacted Name</NavbarBrand>
<NavbarToggler onClick={ () => this.setState({ isOpen: !this.state.isOpen }) } />
<Collapse navbar isOpen={ this.state.isOpen }>
<Nav navbar>
<UncontrolledDropdown className={ "mr-lg-2" } nav inNavbar>
<DropdownToggle nav>
About Us
</DropdownToggle>
<DropdownMenu>
<DropdownItem>
<Link to={ "/" }>Mission Statement</Link>
</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</Nav>
{ userOptions }
</Collapse>
</Navbar>
Now, userOptions is a form that changes based on user input, but all... forms of it take this basic inline form layout, save for differences in buttons and links inside.
<Form className={ "userStatusForm" } inline >
// Content
</Form>
Here's my issue: in the simple layout I'm using, the brand, toggle, nav, and user form pile against each other on the left. However, I'm wanting content inside the Collapse element to use a standard "justify content between" alignment to press the user form against the right side, regardless of its size. That said, I'm struggling to find what I need in the Reactstrap docs - and to phrase what I'm trying to do correctly for Google.
So, I was trying to avoid direct className assignments, since I've already decided to use the Reactstrap library, but the simplest thing involved a mr-auto class added on to the Nav component that forms the first item inside the Collapse container. Not as elegant as I'd hoped, but it's simple (and was good enough for the Navbar in the Reactstrap docs).
I think I have found an error with React-Materialize. Still new, probably won't stop people from being harsh ;).
Using the normal means of changing the text color i.e.
`className="black-text"`
does not work. I was forced to change it manually by finding the element
`nav .brand-logo {
color: black;
}`
and making the change within my own css file. I wanted to stay within the framework, but could not get anything to work. Here is my complete React-Materialize element:
`<Navbar brand="ARWA" className="transparent black-text" right>
<NavItem href="get-started.html">
<div className="blue-text">Getting started </div>
</NavItem>
<NavItem href="components.html">
<div className="blue-text"> Components</div>
</NavItem>
</Navbar>`
I took a look at the source code, but to no avail. No gleaming errors stood out to me. This may be an opportunity for someone better than I to make a contribution. Or at least see what I'm doing wrong and help me change the brand color within the React-Materialize framework.
Changing Text Color of React Attribute
If you want to edit the color of text within an attribute tag or add an image into the tag, you can put your code into a JSX variable and pass that variable into the attribute tag in react-materialize.
Changing Text Color
import YourStuff
import reactThings
const brandColor = <span style={{color: "#FFFFFF"}}>Your Brand</span>;
class Header extends Component {
...
<Navbar className="Header red" brand={brandColor} right />
}
brandColor changes whatever the default color was to #FFFFFF which is white. Make sure brandColor is outside of the component class.
Inserting Image
import Logo as "./logo.png";
const Img = <img src={Logo} alt={"YourBrand"}/>;
class Header extends Component {
...
<Navbar className="Header red" brand={Img} right />
}
The syntax for inserting an image is slightly different so I thought I'd include this in here along with your answer.
According to this you may need to wrap what you want to change in a div and change the class on that. Does that work?
I am using the react-bootstrap library to construct a nav bar at the top of my page using Navbar import. However, the bar seems to have some padding at the bottom which I do not want and can't seem to remove, as seen here (Yellow on bottom. Also navbar component does not seem to span the entire page [as seen by white space on either side of bar]; not sure of why this is either):
I would like the bar to span the page and have no padding on the bottom.
My render method is as follows:
render() {
if(Auth.isUserAuthenticated() && this.props.location.pathname === '/') {
return <div/>;
}
return (
<span className="nav-bar">
<Navbar inverse className="fixed-top collapseOnSelect nav-bar">
<Navbar.Collapse>
<Navbar.Header className="locl-link">
<Navbar.Brand>
<LinkContainer to="/">
<a>locl</a>
</LinkContainer>
</Navbar.Brand>
<Navbar.Toggle />
</Navbar.Header>
<BootstrapNav>
<LinkContainer to="/about">
<NavItem active={this.linkActive("about")}>About</NavItem>
</LinkContainer>
</BootstrapNav>
<BootstrapNav pullRight>
{this.logInOut()}
</BootstrapNav>
</Navbar.Collapse>
</Navbar>
</span>
);
}
Any help would be greatly appreciated.
I didn't realise body tag has default margin; whoops
Just like #Zero wrote .navbar class has margin-bottom: 20px; property. You will need to override it or set margin-top: -20px; on element below if you want to keep it for some other view.
When it comes to padding at the right side - it's left for a vertical scroll bar. I have faced the same issue when I was using react-sidebar.
The space below navbar is coming from .navbar class in bootstrap.css. You can remove the margin-bottom: 20px; in bootstrap.css.
If you’re using bootstrap.css via CDN you can add style to your navbar, like so:
<Navbar style={{marginBottom: "0"}} inverse className="fixed-top collapseOnSelect nav-bar">
Regarding your problem with white space on either side or navbar. I think the problem is with how you render an element into the DOM. You should check the root DOM node in your HTML, maybe it has padding or margin. It could also be from the .nav-bar class in your span, or some other class.