How to add my isLoading constant to this conditional statement? - javascript

I added this constant
const isLoading = !templates;
In order to Change the color of my button and prevent a click if my cards are still loading.
However, I dont know how to add my isLoading constant to this conditional statement.
<MenuButton
className={
!firstTimeOnOnboarding || selectedTemplatesIds.length >= minNumOfOptions
? `${styles.actionBlue}`: `${styles.actionNormal}`}>
{buttonText}
</MenuButton>
I tried doing this but it doesnt work.
className={
!isLoading && !firstTimeOnOnboarding || selectedTemplatesIds.length >= minNumOfOptions ? `${styles.actionBlue}`: `${styles.actionNormal}`}

If you want prevent click, what you do really need is disable button while Loading variable is true, as MenuButton is a custom component, you should create a prop "disabled" to manage button disabling.
This is an example with a HTML button tag. I added global class for the button to manage disabling and common attributes, if you want use more pretty option you can use "classnames package" for use multiples CSS classes
JSX:
<button
className={
!firstTimeOnOnboarding || selectedTemplatesIds.length >= minNumOfOptions
? `${styles.actionBlue} ${styles.myButton}`: `${styles.actionNormal} ${styles.myButton}`}
disabled={isLoading}
>
{ isLoading ? 'Loading' : buttonText}
</button>
I added a CSS class because is a good practice show to user disabled button of visual way, and maybe you wonder how to do it.
CSS:
.actionBlue {
...your styles
}
.actionNormal {
...your styles
}
.myButton {
...if you want common styles, here
}
.myButton:disabled {
opacity: .5;
}
Tips: I manage text my button while it is loading with this conditional.
{ isLoading ? 'Loading...' : buttonText}
Also I think, you should manage disibiling of your button with a "CSS Specificity".
.myButton {
...if you want common styles, here
}
.myButton.actionBlue {
...your styles
}
.myButton.actionNormal {
...your styles
}
.myButton:disabled {
opacity: .5;
}

Related

Overriding antd component style for just one component

Working with antd components, if you have an Alert component, inside there is a tooltip that is given the styling through ​ant-alert-icon​ class. So, if we need to override the Tooltip color, you can have in your stylesheet a class to override the values. For example:
ant-alert-info {
.ant-alert-icon {
color: #3d6de7 !important;
}
}
However, this will apply the color #3d6de7 to all Alerts type Info. How can I apply a different color to just one specific Alert type Info while keeping the styling above for the remaining Alert type Info components? Is this possible? What are the alternatives to doing something similar?
I am able to change the background of the Alert using the style field as follows:
<Alert
description={}
type="info"
showIcon
style={!props.alert ? { backgroundColor: "#F4F0F0"} : { backgroundColor: "#fff2f0", border: "#ffccc7" }}
/>
However, I have not been able to change the Tooltip color.
Thanks!
You can set an additional className like ant-alert-info-custom this way:
<Alert
description={}
type="info"
showIcon
className="ant-alert-info-custom ant-alert-info-custom-with-red-icon"
/>
And use it like this:
.ant-alert-info.ant-alert-info-custom {
// some shared styles by all custom alerts
.ant-alert-icon {
color: #3d6de7 !important;
}
// specific style for red icon
&.ant-alert-info-custom-with-red-icon{
.ant-alert-icon {
color: red!important;
}
}
}
As you can see you can do this:
<ConfigProvider csp={{ nonce: 'YourNonceCode' }}>
<Button>My Button</Button>
</ConfigProvider>
I think you can use ConfigProvider to overwrite Antdesign styles. Check out the link for more info:
ConfigProvider.

I only want a div to display on screen depending on a boolean value

I only want a particular div to display if showHideClassName is set to the value of true. I have this code in my React application so that a div will either display or not depending on the status of showHideClassName:
render() {
...
const showHideClassName = showPrompt ? 'show-div' : 'display-none';
return (
<div className={showHideClassName}>
...
</div>
);
}
The div is always visible though. Is there any way I can get this to work as I desire?
I don't have display-none in my css. Now that I've added the below, it works ad desired.
.display-none { display: none; }

How do I style a div inside a component without passing props to that component (I'm using a package)

I'm using the react-scrollbar package to render a scrollbar for my my content. What I also want is a arrow button that, on click, moves to a certain scrollbar area. The problem is, I'm trying to style (marginTop) a class inside my component.
This is my attempt:
// MY COMPONENT
scrollToNextUpload = () => {
const NextUpload = 400
this.setState({ marginTop : this.state.marginTop + NextUpload }, () => document.getElementsByClassName('scrollarea-content')[0].style.marginTop = "'" + this.state.marginTop + "px'")
}
// MY RENDER
render () {
<ScrollArea>
// my content
<div onClick={this.scrollToNext}></div>
</ScrollArea>
}
What is actually rendered
<div class='scrollarea'>
<div class='scrollarea-content'>
// my content
<div onClick={this.scrollToNext}></div>
</div>
</div>
What I want
To make my area with the scrollbar scroll, I have to add a marginTop style to the 'scrollarea-content'. I could do this by passing props to the < ScrollArea > and then use them inside the installed package; but I'm trying to avoid altering the original package content.Also, is there another way how I could scroll by click and is there someone else who's experienced with that NPM Package?
Most libraries give props to apply style to child components, in this library you can pass a className to the contentClassName or use inline style in contentStyle prop :
<ScrollArea contentStyle={{ marginTop: 10 }}>
An another way is to write css to add style to the scrollarea-content class.
In a .css file :
.scrollarea-content {
margin-top: 10px;
}
Edit: In your case you can programatically change the marginTop style by using the props like this :
scrollToNextUpload = () => {
const NextUpload = 400;
this.setState(prevState => ({ marginTop : prevState.marginTop + NextUpload }));
}
render () {
<ScrollArea contentStyle={{ marginTop: this.state.marginTop }}>
// my content
<div onClick={this.scrollToNext}></div>
</ScrollArea>
}
Note the use of a functional setState to prevent inconsistencies when next state value depends on the previous state.

React, Using Refs to scrollIntoView() doesn't work in componentDidUpdate()

I'm using Redux in my app, inside a Component I want to scroll to an specific div tag when a change in the store happens.
I have the Redux part working so it triggers the componentDidUpdate() method (I routed to this compoennt view already).
The problem as far as I can tell, is that the method scrollIntoView() doesn't work properly cos componentDidUpdate() has a default behavior that scrolls to the top overwriting the scrollIntoView().
To work-around it I wrapped the function calling scrollIntoView() in a setTimeout to ensure that happens afeterwards.
What I would like to do is to call a preventDefault() or any other more elegant solution but I can't find where to get the event triggering the 'scrollTop'
I looked through the Doc here: https://facebook.github.io/react/docs/react-component.html#componentdidupdate
and the params passed in this function are componentDidUpdate(prevProps, prevState) ,since there is no event I don't know how to call preventDefault()
I've followd this Docs: https://facebook.github.io/react/docs/refs-and-the-dom.html
And tried different approaches people suggested here: How can I scroll a div to be visible in ReactJS?
Nothing worked though
Here is my code if anyone has any tip for me, thanks
class PhotoContainer extends React.Component {
componentDidUpdate(){
setTimeout(() => {
this.focusDiv();
}, 500);
}
focusDiv(){
var scrolling = this.theDiv;
scrolling.scrollIntoView();
}
render() {
const totalList = [];
for(let i = 0; i < 300; i += 1) {
totalList.push(
<div key={i}>{`hello ${i}`}</div>
);
}
return (
<div >
{totalList}
<div ref={(el) => this.theDiv = el}>this is the div I'm trying to scroll to</div>
</div>
)
};
}
Ok it's been a while but I got it working in another project without the setTimeOut function so I wanted to answer this question.
Since Redux pass the new updates through props, I used the componentWillRecieveProps() method instead of componentDidUpdate() , this allowes you a better control over the updated properties and works as expected with the scrollIntoView() function.
class PhotoContainer extends React.Component {
componentWillReceiveProps(newProps) {
if (
this.props.navigation.sectionSelected !==
newProps.navigation.sectionSelected &&
newProps.navigation.sectionSelected !== ""
) {
this.focusDiv(newProps.navigation.sectionSelected);
}
}
focusDiv(section){
var scrolling = this[section]; //section would be 'theDiv' in this example
scrolling.scrollIntoView({ block: "start", behavior: "smooth" });//corrected typo
}
render() {
const totalList = [];
for(let i = 0; i < 300; i += 1) {
totalList.push(
<div key={i}>{`hello ${i}`}</div>
);
}
return (
<div >
{totalList}
<div ref={(el) => this.theDiv = el}>
this is the div I am trying to scroll to
</div>
</div>
)
};
}
I also struggled with scrolling to the bottom of a list in react that's responding to a change in a redux store and I happened upon this and a few other stackoverflow articles related to scrolling. In case you also land on this question as well there are a few ways this could be a problem. My scenario was that I wanted a 'loading' spinner screen while the list was rendering. Here are a few wrong ways to do this:
When loading = true, render spinner, otherwise render list.
{loading ?
<Spinner />
:
<List />
}
as stated above this doesn't work because the list you might want to scroll to the bottom of isn't rendered yet.
When loading set the display to block for the spinner and none for the list. When done loading, reverse the display.
<div style={{display: loading ? 'block' : 'none'>
<Spinner />
</div>
<div style={{display: loading ? 'none' : 'block'>
<List />
</div>
This doesn't work either since the list you want to scroll to the bottom of isn't actually being displayed likely when you call the scroll.
The better approach for the above scenario is to use a loading that acts as an overlay to the component. This way both the spinner and list are rendered and displayed, the scroll happens, and when the loading is complete, the spinner can be de-rendered or set to be invisible.

`display: none` vs conditional render in React

I'm having trouble deciding the difference between these two patterns of rendering in React. Hopefully someone can shed some light on this matter.
Pattern 1: React's Conditional Render
https://facebook.github.io/react/docs/conditional-rendering.html
class List extends React.Component {
state = {
menu: false,
}
handleMouseOver = () => {
this.setState({
menu: true
});
}
handleMouseLeave = () => {
this.setState({
menu: false
});
}
render() {
const { menu } = this.state;
return (
<li
onMouseOver={this.handleMouseOver}
onMouseLeave={this.handleMouseLeave}
>
{menu && <Menu />}
</li>
);
}
}
Pattern 2: display: none
.menu {
display: none;
}
.li:hover .menu {
display: block;
}
const List = () => (
<li className="li"><Menu className="menu"/></li>
);
Question:
If I need to render 100 of these items in a single page, which pattern should I go for?
How can I determine which pattern is better?
Are there any performance benefit of using one over the other?
I tend to use display: none in situations where there's a simple condition to show something (e.g hover, etc).
If it's a bit more complex (e.g. click a checkbox to hide an element) then I go with conditional rendering.
The reason behind this is that I don't want to cause state changes and trigger an update for something as trivial as a hover state, and don't want to fiddle around with obscure css classes for things that will have to involve code anyway.
Again, this is my personal preference.
TL;DR: CSS if super simple (e.g. hover), conditional​ render if more logic involved

Categories