Logic to render a component only once - javascript

I need help with creating a logic for my React component. If the divider line appears once on the page it should not be rendered again.
So, if I add the component to the page it styles the text underneath. But if I try to add the component again to the page, the divider line/styling should be ignored. I should only be able to add it once
This is my code:
import React from 'react';
const Divider = () => (
<>
<hr className="divider"/>
</>
);
/* Seperate css file */
hr.divider {
height: 0;
border: 0;
border-top: solid 1px #cdcdcd;
}
hr.divider ~ p.story-text {
font-size: 0.90rem;
font-weight: normal;
font-stretch: normal;
font-style: normal;
letter-spacing: normal;
line-height: 1.75rem;
color:#707174;
#include text-styles(.75rem, 1.75em, "Gordita");
#include breakpoint(tablet) {
#include text-styles(.90rem, 2em, "Gordita");
}
}
hr.divider ~ p.story-text:last-of-type {
border-top: solid 1px red;
}

You need to use the component LifeCycle tools provided by ReactJS. ComponenDidMount() loads the only once when the class is loaded but the render() function is called on each action of the user or the app. Here is a link to ReactJS docs telling how to use ComponentDidMount(): https://reactjs.org/docs/react-component.html#componentdidmount

It may be better to add a condition in the parent component (the one that calls Divider), but given the current snippets:
const Divider = () => (
let dividers = document.getElementsByClassName('divider')
if (dividers.length > 0) {
return null
} else {
return <hr className="divider"/>
}
);
This will not stop your component from rendering. It will only stop more than one hr from rendering.

Related

Next JS styled components dark mode themeing

This probably has answer, but I was unable to find it
I am using styled components with next js and use-dark-mode hook to trigger theme change/detect
global styles switch before loading
import { createGlobalStyle } from "styled-components";
export const GlobalStyles = createGlobalStyle`
body {
background: ${props => props.theme.background};
color: ${props => props.theme.color};
font-family: Roboto, sans-serif;
margin: 0;
padding: 0;
}
`
but having simple styled component like this one
const BackgroundTopAppBar = styled.header`
background-color: ${props => props.theme.appBarHeaderBackground};
`;
doesnt change upon page loading and remains light theme colored
also inside _document.js is implemented next-js team example of how to use styled components for SSR and it works well, but for styled components that are not global dark mode is not activated after page is refreshed
thank you
For anybody looking for a solution, use GlobalStyles and in there modify current color of element because GlobalStyles will apply it before loading
export const GlobalStyles = createGlobalStyle`
body {
background: ${props => props.theme.background};
color: ${props => props.theme.color};
font-family: Roboto, sans-serif;
margin: 0;
padding: 0;
}
${BackgroundTopAppBar} {
background-color: ${props => props.theme.appBarHeaderBackground};
}
`

styled components / react

Im working on a simple button example which i plan to extend. I have added a new button and included some constants as well. so far so good. In case i want to use more button versions like version1, version2, version3 of the same button with some styles changed like the background color. How should i do that? And how should they be exported?
const PrimaryButton = styled.button`
font: inherit;
padding: 0.5em 1em;
border: 1px solid;
background-color: ${buttonBackgroundColor};
color: ${buttonColor};
border-radius: 0.25em;
border-color: ${colors.blueLight};
margin-right: 0.5em;
cursor: pointer;
outline:none;
:hover {
background-color: ${colors.blueLight};
}
`;
Maybe it is possible to extend the button (how?) or does it make more sense to add different components for each button? For my typography i have use "extend". That works. How would that be for the different button versions? Is there a similar way?
export const H1 = styled.h1`
font-size: 30px;
color: red;
`
export const H2 = H1.withComponent('h2').extend`
font-size: 24px;
`
It was working as i added a new component. I imported the PrimaryButton into the new defined component called "Version2".
import PrimaryButton from './primary';
From here i updated the PrimaryButton like this:
const Version2 = PrimaryButton.extend`background-color: red;`
This has the advantage that we have a master component for a button. Now we are able to extend the master with diversity of additional styles. In my case background-color.
With the help of
export default Version2;
we are now able to add this button called "Version2" into our render function like:
<PrimaryButton>ClickMe!</PrimaryButton>
<Version2>ClickMe!</Version2>
and now we get the different buttons. And it´s very modular and clean as well.

reactJS not applying styles (.less files)?

I have been trying to search on the topic but it seems that I might be using the wrong terms as I cannot find any information....
I am trying to get this package to work..(https://github.com/wangzuo/input-moment)
I have succeeded in getting the calendar to work, it saves the date, but it will not switch to the time tab and it also does not style correctly, even though I have imported the .less files into my react component.. the file looks like this...
require('input-moment/src/less/input-moment.less')
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import moment from 'moment';
import InputMoment from 'input-moment';
class Date extends Component {
constructor(props) {
super(props);
this.state = {m: moment()}
}
handleChange(m) {
this.setState({ m });
}
handleSave() {
console.log('saved', this.state.m.format('llll'));
}
render () {
return (
<InputMoment
moment={this.state.m}
onChange={this.handleChange}
onSave={this.handleSave}
/>
)
}
}
and yet my component looks like this...
Can you see any obvious reason as to why the component will not style correctly like the example on github...(http://wangzuo.github.io/input-moment/)
You probably aren't getting the styles provided by the package. If you used npm to install the package, then your import statement could look like this:
require('input-moment/dist/input-moment.css')
Also, compare your App.css to the CSS used by the package author in the example, which can be found at https://github.com/wangzuo/input-moment/blob/master/example/app.less, source is repeated below
*, *:before, *:after {
box-sizing: border-box;
}
body {
margin: 0;
font: 87.5%/1.5em 'Lato', sans-serif;
}
.app {
max-width: 400px;
margin: 0 auto;
margin-top: 90px;
padding: 0 20px;
.input {
margin-bottom: 20px;
}
input {
padding: 7px 8px;
font-size: 14px;
width: 100%;
}
}

Component Not Rendering Properly in React when using CSS hover pseudo selector

My component is a basic NavBar with different items. When Hovering over the item with the dopdiwn-items class, the NavBar should display those items in a block. Instead, only the first item can be seen, with the others being hidden. The same code, when put into plain HTML and CSS on code pen, works as expected. I discovered if I increase the size of the navbar then the items do show as a large block of text. I listed screenshots, and my code below.
CodePen link: http://codepen.io/anon/pen/dvNvmM
Parent Container:
/*Start dependencies*/
import React, { Component, PropTypes } from 'react';
import Picture from '../../components/picture.jsx';
import ShoppingCart from '../../components/shoppingcart.jsx';
import NavBar from '../../components/navbar.jsx';
import { browserHistory } from 'react-router';
import cart from '../../reducers/index.js';
/*Flag set to know if the client recieved and loaded
Will be set to True once the response from the server
Is loaded and parsed*/
var flag = true;
//Start React class
export default class Products extends Component {
constructor(props) {
super(props);
this.state = {clothingData: 0}
}
render(){
/*if the flag variable is false, server is not done yet retriving
data from the DB and parsing it, thus nothing displayed
*/
if (!flag){
return (
<div>
</div>
);
}
//If flag is true (data is ready to be displayed)
else{
//console.log(this.state.clothingData[0].path);
//console.log(this.state.clothingData[0].fileName);
//console.log(this.state.clothingData);
return (
<div>
<NavBar />
<Picture className = "test" src = {this.state.clothingData} onClick = { () => {browserHistory.push('/Product'); }} name = {"joe"} />
</div>
);
}
}
}
JSX:
import React, { Component, PropTypes } from 'react';
export default class NavBar extends Component {
render(){
return(
<ul className="navbar">
<li className="dropdown">
Clothes
<div className="dropdown-items">
Item
Item
Item
Item
</div>
</li>
<li>About</li>
<li>Policies</li>
<li>How To Rent</li>
<li>Contact</li>
</ul>
);
}
}
CSS:
/*Main HTML Stylesheet*/
html{
font-family: sans-serif;
}
/*div{
background:white;
}*/
/********* NavBar Section **********/
.navbar {
overflow: hidden;
background-color:#B597C3;
}
/* links inside the navigation bar */
.navbar li {
float: left;
display: block;
color: #f2f2f2;
text-align: center;
padding: .625em 5em;
text-decoration: none;
font-size: 17px;
}
/* color of links on hover */
.navbar a:hover {
color:#ffffff;
text-decoration: underline;
}
.navbar a.active {
text-decoration:underline;
}
/* Drop Down Items */
.dropdown-btn {
float:left;
font-size: 1.0625em;
color:white;
border: none;
cursor: pointer;
overflow:hidden;
}
.dropdown{
display: inline-block;
}
.dropdown-items{
position:absolute;
display: none;
margin:0;
min-width: 10em;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
}
.dropdown-items a {
color:white;
padding: 12px 50px;
text-decoration: none;
display: block;
}
.dropdown:hover .dropdown-items {
display: block;
position: absolute;
width: 100%;
height: 100%;
}
/********* NavBar Section **********/
When Hovered:
When Hovered w/ increased size:
Okay, so I think you should not use CSS pseudo selectors with React. I've read questions like this one and my conclusion is in React you should handle the onMouseEnter and onMouseLeave events yourself and then keep a component state that indicates whether the dropdown should be shown or not.
That is the React way of usually doing things: hook up event handler functions and use the component state. When the handler functions are called, you change the state.
I don't know whether CSS pseudo selectors will work properly with React. You can take a look at this GitHub issue. My guess is that whatever you are trying to do doesn't work with the CSS selectors because React uses a virtual DOM and not the actual DOM. So the CSS would be changing the DOM directly kind of thing? It would be nice if other more knowledgeable people could comment on that.
For now, I think you should follow the React way of doing things. Here is the code for what you are trying to do:
import React, { Component, PropTypes } from 'react';
export default class NavBar extends Component {
state = {
showDropdown: false
}
renderDropdown() {
return (
<div className="dropdown-items">
Item
Item
Item
Item
</div>
);
}
render() {
return (
<ul className="navbar">
<li
className="dropdown"
onMouseEnter={() => this.setState({ showDropdown: true })}
onMouseLeave={() => this.setState({ showDropdown: false })}
>
Clothes
{this.state.showDropdown ? this.renderDropdown() : null}
</li>
<li>About</li>
<li>Policies</li>
<li>How To Rent</li>
<li>Contact</li>
</ul>
);
}
}
Keep in mind you should remove the CSS rule for the hover pseudo selector for the items div, as well as the display: none for the dropdown. After doing that, everything should be OK.
Note: I used a property initializer to set up the initial state for the component. Babel should take care of transpiling that. In case that doesn't work, set the initial state in the constructor.

How to prevent outside CSS from adding and overriding ReactJS component styles

I have a custom ReactJS component that I want to style in a certain way and provide as a plugin to many different web sites. But when web sites use global styles (Twitter bootstrap or another css framework) it adds and overrides styles of my component. For example:
global.css:
label {
color: red;
font-weight: bold;
}
component.js:
class HelloMessage extends React.Component {
render() {
let style = {
color: "green"
};
return (<label style={style}>Hello</label>);
}
}
result:
Above I didn't use "font-weight: bold" in my component's style but in result my component is using it.
I'd like to be able to encapsulate my custom components's styles in a way that makes them look the same across all the web sites.
The best approach in my view is to define some kind of reset class for your component and put in a set of css resets you can find out there
(e.g. http://meyerweb.com/eric/tools/css/reset/)
The definition in a sass file could look like this:
.your-component-reset {
div, span, object, iframe {
margin: 0;
padding: 0;
border: 0;
font-weight: normal;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
// add some more reset styles
}
To avoid writing a lot when you don't want to use sass just use the universal selector *:
.your-component-reset * {
margin: 0;
padding: 0;
font-weight: normal;
// other reset styles ...
}

Categories

Resources