Css style active in react components - javascript

Alright,so I have SPA without other urls,everything is on one page and I made it when you click on navbar link it scrolls down to that component.
Now I want to make that link active when they click or when they scroll down to it.
Help appreciated.😊
I tried onClick function with forEach removing active class on all links and then adding it to the clicked livk via event,but there are weird bugs..

You must have it installed
npm i react-router-dom
See here for full details
A is a special kind of that knows whether or not it
is "active". This is useful when building a navigation menu such as a
breadcrumb or a set of tabs where you'd like to show which of them is
currently selected. It also provides useful context for assistive
technology like screen readers.
By default, an active class is added to a component when it
is active. This provides the same simple styling mechanism for most
users who are upgrading from v5. One difference as of v6.0.0-beta.3 is
that activeClassName and activeStyle have been removed from
NavLinkProps. Instead, you can pass a function to either style or
className that will allow you to customize the inline styling or the
class string based on the component's active state. You can also pass
a function as children to customize the content of the
component based on their active state, specially useful to change
styles on internal elements.
import * as React from "react";
import { NavLink } from "react-router-dom";
function NavList() {
// This styling will be applied to a <NavLink> when the
// route that it links to is currently selected.
let activeStyle = {
textDecoration: "underline",
};
let activeClassName = "underline";
return (
<nav>
<ul>
<li>
<NavLink
to="messages"
style={({ isActive }) =>
isActive ? activeStyle : undefined
}
>
Messages
</NavLink>
</li>
<li>
<NavLink
to="tasks"
className={({ isActive }) =>
isActive ? activeClassName : undefined
}
>
Tasks
</NavLink>
</li>
<li>
<NavLink to="tasks">
{({ isActive }) => (
<span
className={
isActive ? activeClassName : undefined
}
>
Tasks
</span>
)}
</NavLink>
</li>
</ul>
</nav>
);
}
See here for full details

Related

Dropdown layout on hover for multiple elements

I face a problem with react.js, I'm new to it and haven't seen such questions as mine so far.
My problem is that I wanted to reproduce epic games website to learn react, but I can't manage to do the dropdown layout menu.
So here is what I've done so far (tried many things but my final result is this) :
const [selectedMenu, setSelectedMenu] = useState(null);
And the html part :
<div className="col-2" onMouseEnter={() => setSelectedMenu(1)}>
<div className="wrapper">
<li className="select-none bot_line">news & events</li>
</div>
{selectedMenu === 1 && (
<div
className="bot_menu"
onMouseEnter={() => setSelectedMenu(1)}
onMouseLeave={() => setSelectedMenu(null)}
>}
But this is not what I want exactly, I have 7 element to set from hidden to visible.
The way I want to do it is by targeting each child components with the "onMouseEnter" function through the col-2 element.
What I wish is to change the previous class to a new one by hovering col-2 to show the bot_menu onMonseEnter.The css part is done, my trouble is only with the react part.
So the previous className to be "hidden" and onMouseEnter set it to "visible" className.
And to do it by targeting child elements so I only have to do it once and not 7 times.
Please

react-select dropdown opens inside modal

I have a custom modal where I have 2 react-select components inside. The modal body is ready to auto scroll in case the content exceeds its size, but the react-select components dropdown open inside the modal with this overflow, which is what i am not looking for. Without overflow, it works fine.
I'm working with CSS Modules.
<div className={styles.modalBody}>
{this.props.children}
</div>
.modalBody {
padding: padding;
flex: 1 1 auto;
height: 45vh;
max-height: 100%;
overflow: auto;
}
<Select
id={this.props.id}
className={styles[this.props.selectType ? this.props.selectType : 'selectWhite']}
classNamePrefix="select"
name={this.props.name}
value={selectedOption ? selectedOption : this.props.value}
placeholder={this.props.placeholder}
onChange={this.onChange}
options={this.props.options}
isDisabled={this.props.disabled}
isSearchable={false}/>
How can I fix this?
Thank you! :)
You want to look at the menuPortalTarget prop. There's a topic on this in the Advanced documentation, specifically with a modal example provided. Something like:
<Select
{...otherProps}
menuPortalTarget={document.body} />
You can use Menu Position as fixed by setting the prop,which in turn makes your dropdown as position fixed as
<Select menuPosition="fixed" />
A full example of how to display the select menu in a modal (I added comments at important lines and a step-by-step explanation below):
import React, { useRef } from 'react';
import Select from 'react-select';
import { Dialog } from '#mui/material';
const MyModal: React.FC = () => {
const ref = useRef<HTMLDivElement>(null);
return (
<Dialog
// ...
ref={ref} // stores a ref to the DOM node of the modal component
>
<Select
// ...
menuPortalTarget={ref.current} // pass the ref to `Select` to portal the select menu to the given DOM node
styles={{
menuPortal: defaultStyles => ({
...defaultStyles,
paddingBottom: '10px', // style the menu when it's portalled into the DOM node given to `menuPortalTarget`
}),
}}
/>
</Dialog>
);
};
export default MyModal;
Step-by-step explanation:
I create a ref with the React.useRef hook.
I'm getting a reference of the Dialog component (which in this example is a MUI dialog component (but could be any other Modal component) via ref={ref}
I pass that ref to react-select's Select component via menuPortalTarget={ref.current}.
I had to customize the placement of the menu via paddingBottom: '10px', because the menu would appear a bit too high in my case. You might have to adjust this differently.
Further comments:
document.body didn't do the trick for me. The menu appeared behind the modal for me in this case.
Unfortunately the react-select portaling docs do not contain any example code, so I hope this example is helpful to you.

Switch CSS classes with state [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I am currently creating with React a login/register template which mimics in functionality the groupon login. Specifically, I am targeting the switching of the colored border when toggling between i have an account and i'm a new customer. The template is very common in today's development, and I have seen many poorly coded solutions which ignore best practices altogether.
I'll start by stating that the best solution uses state.
I would then create the following (incomplete, obviously):
<div className="wrapper">
<div className="login" />
<div className="register" />
</div>
I then thought to give both divs a state, and a border-bottom spec to render the colored border. The issue I am seeing is how to best implement the toggle of which one is active.
Another thought experiment is to hardcode everything up to the input fields. Then, when the user clicks on the I'M A NEW CUSTOMER field, all I have to do is set an active state to that component, and render .
Again, the point of this question is to answer how to best implement this login/registration form. By the way, Groupon gives their showing component a class of active.
EDIT: As was pointed out by Sunny Wong, and reflective of my assumption, his solution uses state and implements with my component as follows:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
activeTab: "login"
};
}
handleActiveTab = name => event => {
this.setState({ activeTab: name });
};
render() {
const { activeTab } = this.state;
let joinComponent =
activeTab === "login" ? <LoginComponent /> : <RegisterComponent />;
return (
<div className="wrapper">
<div
onClick={this.handleActiveTab("login")}
className={classNames("login", {
active: activeTab === "login"
})}
>
Login
</div>
<div
onClick={this.handleActiveTab("register")}
className={classNames("register", {
active: activeTab === "register"
})}
>
Register
</div>
{joinComponent}
</div>
);
}
}
Also, the post was tagged as too broad, yet I targeted specific topics/questions. To summarize, they were:
Specifically, I am targeting the switching of the colored border when
toggling between i have an account and i'm a new customer.
answer how to best implement this login/registration form
See the live version for further reference.
Toggling the classes is the way to go here. There is no need to re-render the tabs as different components, as the content is the same. The tabs only undergo a cosmetic change. There is a library called classNames (https://www.npmjs.com/package/classnames), which is extremely helpful in controlling which classes get applied in a given situation.
Something like keeping state of which link is active via an id. Then toggle an 'active' class which is responsible for applying the active styling.
state = { activeTab: 'login' }
handleActiveTab = e => {
//sets state of activeTab
}
render() {
const { activeTab } = this.state;
return (
<div className="wrapper">
<div onClick={this.handleActiveTab} className={classNames('login', { active: activeTab === 'login' })} />
<div onClick={this.handleActiveTab} className={classNames('register', { active: activeTab === 'register' })} />
</div>
);
}
<div className="wrapper">
<div className={`login ${this.state.active==CONST.LOGIN? 'active':''}`} onClick={e=>{this.setState({active:CONST.LOGIN}}/>
<div className={`register ${this.state.active==CONST.REGISTER? 'active':''}`} onClick={e=>{this.setState({active:CONST.REGISTER}} />
</div>
you have to maintain state for active in active that will allow you to load right component (login/register). CONST.LOGIN and CONST.REGISTER are constants that you have to manage. you can use just 1/2 the dirty way.

react and bootstrap v4 delay collapse to render component

I am using React and bootstrap 4 to generate a collapsible div. Inside this div I have another React component, like this:
ComponentA
<a name={name}
className={'btn btn-primary'}
data-toggle={'collapse'}
href={'#collapseId'}
role={'button'} aria-expanded={'false'}
aria-controls={'collapseId'}>
collapse
</a>
<div id='collapseId'>
<ComponentB/>
</div>
This works correctly, but when I render ComponentA multiple times (I need to render it more than 20 times) I get performance issues, because ComponentB includes many divs and buttons.
So what I want to do is to render conditionally ComponentB but keep bootstrap's collapse transitions.
Now, if I want to conditionally render, I do this:
constructor(props){
super(props);
this.state={collapsed=true}
}
conditionalRender(e){
this.setState(prevState => this.state.collapsed = !prevState.collapsed)
}
And then in the render function:
<a name={name}
className={'btn btn-primary'}
data-toggle={'collapse'}
href={'#collapseId'}
role={'button'} aria-expanded={'false'}
aria-controls={'collapseId'}
onClick={(e)=>this.conditionalRender(e)}>
collapse
</a>
<div id='collapseId'>
{!this.state.collapsed &&
<ComponentB/>
}
</div>
And it works, BUT the transition is laggy, not fluid and doesn't look good.
Is there a way to delay the transition of the collapsed transition for this to work and be fluid? I've seen some overrides to css transition, but again, not fluid.
Another valid option would be to use the callback function of setState to execute the default anchor's functionality but I don't know how to.
bootstrap 4.1
react 16.4.2

Show/Hide ReactJS components without losing their internal state?

I've been hiding/showing react components by not rendering them, for example:
render: function() {
var partial;
if (this.state.currentPage === 'home') {
partial = <Home />;
} else if (this.state.currentPage === 'bio') {
partial = <Bio />;
} else {
partial = <h1>Not found</h1>
}
return (
<div>
<div>I am a menu that stays here</div>
Home Bio
{partial}
</div>
);
}
but just say that the <Bio/> component has lots of internal state. Everytime I recreate the component, it loses it's internal state, and resets to it's original state.
I know of course that I could store the data for it somewhere, and pass it in via props or just globally access it, but this data doesn't really need to live outside of the component. I could also hide/show components using CSS (display:none), but I'd prefer to hide/show them as above.
What's the best practice here?
EDIT: Maybe a better way to state the problem is to use an example:
Ignore React, and assume you were just using a desktop app that had a configuration dialog with a Tab component called A, which has 2 tabs, named 1 and 2.
Say that tab A.1 has an email text field and you fill in your email address. Then you click on Tab A.2 for a second, then click back to Tab A.1. What's happened? Your email address wouldn't be there anymore, it would've been reset to nothing because the internal state wasn't stored anywhere.
Internalizing the state works as suggested in one of the answers below, but only for the component and it's immediate children. If you had components arbitrarily nested in other components, say Tabs in Tabs in Tabs, the only way for them to keep their internal state around is to either externalize it somewhere, or use the display:none approach which actually keeps all the child components around at all times.
It just seems to me that this type of data isn't data you want dirtying up your app state... or even want to even have to think about. It seems like data you should be able to control at a parent component level, and choose to either keep or discard, without using the display:none approach and without concerning yourself with details on how it's stored.
One option would be to move the conditional inside the component itself:
Bio = React.createClass({
render: function() {
if(this.props.show) {
return <p>bio comp</p>
} else {
return null;
}
}
});
<Bio show={isBioPage} />
Whether this is "best practise" or not probably depends on the exact situation.
Unfortunately, style={{display: 'none'}} trick only works on normal DOM element, not React component. I have to wrap component inside a div. So I don't have to cascade the state to subcomponent.
<div className="content">
<div className={this.state.curTab == 'securities' ? 'active' : ''}>
<Securities />
</div>
<div className={this.state.curTab == 'plugins' ? 'active' : ''}>
<Plugins />
</div>
</div>
Looks like official documentation suggests hiding stateful children with style={{display: 'none'}}
The fundamental problem here is that in React you're only allowed to mount component to its parent, which is not always the desired behavior. But how to address this issue?
I propose the solution, addressed to fix this issue. More detailed problem definition, src and examples can be found here: https://github.com/fckt/react-layer-stack#rationale
Rationale
react/react-dom comes comes with 2 basic assumptions/ideas:
every UI is hierarchical naturally. This why we have the idea of components which wrap each other
react-dom mounts (physically) child component to its parent DOM node by default
The problem is that sometimes the second property isn't what you want
in your case. Sometimes you want to mount your component into
different physical DOM node and hold logical connection between
parent and child at the same time.
Canonical example is Tooltip-like component: at some point of
development process you could find that you need to add some
description for your UI element: it'll render in fixed layer and
should know its coordinates (which are that UI element coord or
mouse coords) and at the same time it needs information whether it
needs to be shown right now or not, its content and some context from
parent components. This example shows that sometimes logical hierarchy
isn't match with the physical DOM hierarchy.
Take a look at https://github.com/fckt/react-layer-stack/blob/master/README.md#real-world-usage-example to see the concrete example which is answer to your question (take a look at the "use" property):
import { Layer, LayerContext } from 'react-layer-stack'
// ... for each `object` in array of `objects`
const modalId = 'DeleteObjectConfirmation' + objects[rowIndex].id
return (
<Cell {...props}>
// the layer definition. The content will show up in the LayerStackMountPoint when `show(modalId)` be fired in LayerContext
<Layer use={[objects[rowIndex], rowIndex]} id={modalId}> {({
hideMe, // alias for `hide(modalId)`
index } // useful to know to set zIndex, for example
, e) => // access to the arguments (click event data in this example)
<Modal onClick={ hideMe } zIndex={(index + 1) * 1000}>
<ConfirmationDialog
title={ 'Delete' }
message={ "You're about to delete to " + '"' + objects[rowIndex].name + '"' }
confirmButton={ <Button type="primary">DELETE</Button> }
onConfirm={ this.handleDeleteObject.bind(this, objects[rowIndex].name, hideMe) } // hide after confirmation
close={ hideMe } />
</Modal> }
</Layer>
// this is the toggle for Layer with `id === modalId` can be defined everywhere in the components tree
<LayerContext id={ modalId }> {({showMe}) => // showMe is alias for `show(modalId)`
<div style={styles.iconOverlay} onClick={ (e) => showMe(e) }> // additional arguments can be passed (like event)
<Icon type="trash" />
</div> }
</LayerContext>
</Cell>)
// ...

Categories

Resources