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).
Related
I'm using React router dom Link component. It is basically twitter's home feed. I want to be able to have two type of Links in one div component. One will be Link to go to user's profile and other one to go to post. I am currently getting warning and couldn't find solution for now. Here is the screenshot as reference:
I understand the issue here, my post Link is the parent element and I've added two user Link components inside of it as the user should be able to access post page when he clicks on anything inside of the post except user's profile photo and user's name. Is there any smarter way of achieving this and keeping links like this?
Code:
{posts?.map((post) => (
<Link
className={classes.link}
key={post.user.id}
to={`/posts/${post.id}`}
>
<div className={classes.post}>
<Link to={`/users/${post.user.id}`}>
<img
className={classes.profileImage}
src={DefaultLogo}
alt="default-profile"
/>
</Link>
<article className={classes.postDetails}>
<Link
className={classes.link}
to={`/users/${post.user.id}`}
>
<Typography
variant="subtitle1"
className={`${classes.postTitle} ${classes.content}`}
>
{post.user.name}
</Typography>
</Link>
<Typography
variant="subtitle1"
className={`${classes.postText} ${classes.content}`}
>
{post.body}
</Typography>
</article>
</div>
</Link>
))}
Yes, having anchor tags inside of another anchor tag is misleading a bad approach to doing things. But given your requirements you can make use of a basic button with react router dom history api.
A simple example:
import {Link, useHistory} from 'react-router-dom'
const App = () => {
const history = useHistory()
return (
<a
href='/user/1'
>
<h2>John doe</h2>
<div>here are some use information</div>
{/* Need to prevent the event bubbling */}
<Link role='link' to='/users/1/posts'>
User posts
</Link>
</div>
)
}
Is there a way to make the Fluent UI (formerly Office Fabric UI) Nav component correctly work replacing it's <a> element links with a custom link such as <Link> from Reach Router?
Fluent UI Nav provides an onRenderLink props but that only changes the inner content innermost <a> element. It leaves the outer wrapping element with a traditional <a> which causes full page re-renders when the user uses it.
It also provides the linkAs prop but that changes the entire content of the "Group Header" and takes a way all of the nice CSS styling advantages of using the Nav in the first place.
Is there a way to actually get this working?
I did a little more googling and found this codepen which uses LinkAs :
(props) => {
return <Link className={props.className} style={{color: 'inherit', boxSizing: 'border-box'}} to={props.href}>
<span style={{display: 'flex'}}>
{ !!props.iconProps && <Icon style={{margin: '0 4px'}} {...props.iconProps} /> }
{props.children}
</span>
</Link> ;
}
A little bit disappointing that you basically have to reverse engineer their CSS and render it yourself in order to get this working.
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 am using react and semantic. I am using the multiple sidebar example. The idea is that the left hand sidebar offers up some menu options, and then the right hand sidebar is the sub menu based on which option from the left menu is chosen. When a sub menu item is selected, a component is added to the Sidebar.Pusher, i.e displayed on the page.
It all works except re-rendering the content of the Sidebar.Pusher. This apparently only updates when the left hand side bar's visibility changes. I am using redux/rematch to handle state, and can see that the state that holds the content of the Sidebar.Pusher is being updated, but `render() is only being called when visibility changes of the sidebar.
The content of Sidebar.Pusher is an array, and I even tried displaying on the page the length of the array, which is being updated (pushed into) each time an item on the right hand sidebar is clicked. However this doesn't cause a render() to be fired, its literally when the left hand sidebar visibility changes.
Just to note, I did see this issue, however its from last year, and the answer wasn't enough for me to be able to fix the issue. Help would be appreciated.
Structure:
Index.js renders App.js, App.js renders Menu.js (which is a semantic set of tabs). One of the menu options is Sidebar.js which renders:
<Sidebar.Pushable as={Segment}>
<Sidebar
as={Menu}
animation="overlay"
direction="right"
inverted
vertical
visible={secondaryVisibility}
width="wide"
>
{focusedList.map((el, i) => {
return (
<Menu.Item key={i} as="a" onClick={() => this.addSegment(el)}>
<Article el={el} />
</Menu.Item>
)
})}
</Sidebar>
<Sidebar
as={Menu}
animation="overlay"
icon="labeled"
inverted
// onHide={this.handleSidebarHide}
vertical
visible={primaryVisibility}
width="wide"
>
<Menu.Item
onClick={() => this.changeTab(menuItem)}
as="a"
name="menuItem"
header
>
Menu Item
</Menu.Item>
</Sidebar>
<Sidebar.Pusher style={{ minHeight: "600px" }}>
<Segment basic>
{segments.map((el, i) => {
console.log(`el ${el}`)
return <Content key={i} segment={el} />
})}
</Segment>
</Sidebar.Pusher>
and all state (secondaryVisibility etc) is stored in rematch
Thanks
I haven't been able to identify the problem based on the code you've posted, could you provide more info such as the entire Sidebar.js and maybe what's in the Content component?. My guess would be that there's a HOC or lifecycle method getting in the way.
I've created a trivial example that seems to work fine, if I understand what you're trying to accomplish: https://codesandbox.io/s/myl6xpz9py
I got it. I forgot about immutability in state. Perhaps someone will benefit from this.
I was trying to update a state array with
let tmp = prevState.contract.segments
tmp.push(segment)
this.update({ segments: tmp })
However, this won't work as tmp is a reference to prevState.contract.segments, so this won't work, as pushing to tmp is equivelent to pushing to prevState.contract.segments.
you have to have a completely new array:
const tmp = [...prevState.contract.segments, segment]
this.update({ segments: tmp })
Now it works.
I have run into a situation where it seems I need to pass the children of one component over to another that is a sibling of the original. This doesn't sit well with me as it seems to go against what I've learned is the proper hierarchy and communications channels in React. I need the components to render as siblings due to styling issues, but I'd like to have a logical grouping of components for developers utilising my component.
In short I have some buttons and some of these buttons display a drop-down menu. Like a toolbar of sorts. I want the menu to pop up in a modal like way and so I don't want to place a sub-div next to the button. Instead I want it to render below the buttons and just swap its components with whatever menu is currently active.
Here is how I envision the rendering to look:
<ul>
<li><button>Triggers some action elsewhere</button></li>
<li><button>Button with menu</button></li>
<li>Link</li>
<li><button>Button with menu</button></li>
<li><button>Triggers some action elsewhere</button></li>
</ul>
<div class="menu-container">
Menu content goes here
</div>
Since the buttons are 1-1 linked with a menu I want the developer to work with the components like this:
<Nav>
<NavButton text="Triggers some action elsewhere"/>
<NavMenu text="Button with menu">
<Link to="/">A link</Link>
<Box>
...
</Box>
</NavMenu>
<NavLink>
<Link to="/">Link</Link>
</NavLink>
<NavMenu text="Button with menu">
<Link to="/">A link</Link>
<Box>
...
</Box>
</NavMenu>
<NavButton text="Triggers some action elsewhere"/>
{/*
This component is dynamically inserted by <Nav/> at this position.
It is responsible for rendering a floating menu and controlling its
behaviour.
*/}
<FloatingMenu></FloatingMenu>
</Nav>
The <Nav> component would then swap the content of the .menu-container div based on whether a menu was open or not.
EDIT!
I forgot to mention that there is a separate component here that the developer doesn't see. The <FloatingMenu> component is dynamically inserted by <Nav> and not actually part of the set of children that the developer will write. It is responsible for rendering the actual menu div and controlling its behaviour. So what I'd like to do is move all children from the currently active <NavMenu/> component into the <FloatingMenu/> and empty it out if no menus are active. At least that was my original idea.
/EDIT!
Can this be done? Am I over complicating or misunderstanding something? Any help would be much appreciated!