can i use ternary operator in className of div? - reactjs

can i do the following?
<div className={`${customerDetails.isCustomer} ? u-pb--sm : u-ph--sm u-pb--sm`}>
If not what is the best way to write this?
Thanks

That should work. Check customerDetails and try to console.log it.
const CustomerDetails = ({ customerDetails }) =>
<div className={customerDetails.isCustomer ? 'customer': 'notCustomer'}>
{`Customer: ${customerDetails.isCustomer}`}
</div>
class App extends React.Component {
render() {
const customerDetails1 = { isCustomer: true }
const customerDetails2 = { isCustomer: false }
return (
<div>
<CustomerDetails customerDetails={customerDetails1} />
<CustomerDetails customerDetails={customerDetails2} />
</div>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
)
.customer {
background-color: green;
color: white;
}
.notCustomer {
background-color: red;
color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

It works. I use it all the time. As others have asked, what does your render function look like? The true way of calling the render function again (incorporating changes in your DOM) is using this.setState. If you use a this.state.something as your ternary boolean, your className will dynamically update every single time you change it using this.setState.

Related

Scroll to a component when a button is clicked in React JSX

I've looked at way too many ways to scroll to a certain component when clicking a button, but it's always in a JS file. Can't seem to get it to work in my JSX files project.
I've tried several libraries and methods such as "scrollTo", "scrollIntoView", "scrollToComponent"..
They pretty much all try to reference a component, but I can't seem to get it to work.
In JS it usually works when they use the "useRef" from react but, again, can't seem to do it in JSX.
Does anyone have any idea why and how to do it?
Something like:
const MyComponent = () => {
const scrollSomewhere = () => {
// PSEUDO-CODE - something along these lines maybe?
// scrollToComponent("Somewhere");
}
return (
<>
<MyCustomButton onClick={scrollSomewhere}> Click me! </MyCustomButton >
(...)
<MyCustomComponent ref="Somewhere"> I'm somewhere </MyCustomComponent>
</>
}
The ref needs to hold a reference the DOM element to which you want to scroll. Here's an example:
.container {
font-family: sans-serif;
}
.target {
background-color: black;
color: white;
margin: 100rem 0;
padding: 1rem;
}
<script src="https://unpkg.com/react#17.0.2/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#17.0.2/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/#babel/standalone#7.16.3/babel.min.js"></script>
<div id="root"></div>
<script type="text/babel" data-type="module" data-presets="react">
const {useRef, useState} = React;
function Example () {
const elementRef = useRef(null);
const handleClick = () => {
if (elementRef.current) {
elementRef.current.scrollIntoView();
}
};
return (
<div className="container">
<div>The element you want to scroll to is below 👇</div>
<button onClick={handleClick}>Scroll to element</button>
<div className="target" ref={elementRef}>Here I am!</div>
</div>
);
}
ReactDOM.render(<Example />, document.getElementById('root'));
</script>

Can we use class components as children for functional components in React?

Can we have stateful components as children for a stateless functional component?
Short answer: yes.
class B extends React.Component {
render() {
return <div>Class Component</div>
}
}
const A = () => <div className="a">Stateless Functional Component <B /></div>
ReactDOM.render(<A />, document.getElementById('app'));
.a {background: red; padding: 5px;}
.a div {background: green;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>
Sure no problem, you just need to be aware that it re-renders the children if you didn't redefined shouldComponentUpdate or to use React.memo
shouldComponentUpdate(nextProps) {
return (this.props.val !== nextProps.val);
}
For further reading:
https://reactjs.org/docs/react-component.html#shouldcomponentupdate
https://reactjs.org/docs/hooks-faq.html#how-do-i-implement-shouldcomponentupdate

Not Able to Toggle Class Using React Componnent

Can you please take a look at this demo and let me know why I am not able to toggle .green class for #root using onClick in react js?
function toggler(e){
var x = document.getElementById("root");
x.classList.toggle('green');
}
const Button = ({ styleClass, onClick, text }) => {
return (
<button
type="button"
onClick={e => onClick(e)}
className={`btn ${styleClass}`}
>
{text}
</button>
);
};
ReactDOM.render(
<div>
<Button styleClass="btn-primary" text='Primary Button' onClick={toggler} />
</div>
, window.root);
#root{
height:300px;
width:300px;
background:khaki;
}
.green{
background:green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<div id="root"></div>
You should not touch the DOM directly when you're writing React components. React can help you manage your class name with state.
Do something like this:
import React, { Component } from 'react';
export default class Button extends Component {
constructor(props) {
super(props);
this.state = {
buttonStyleClass: 'bar'
}
}
toggler = (e) => {
this.setState({
buttonStyleClass: 'foo'
})
}
render() {
return (
<div
className={this.state.buttonStyleClass}
onClick={this.toggler}
>
Click me
</div>
);
}
}
The problem here is that id-selectors have higher priority over class-selectors in css. Since you have defined the base color with #root, you can't toggle it with just .green.
Many solutions here, but one of them could be #root.green, adding !important or selecting your root otherwise.
That being said, you should not mutate the DOM directly when using React. It voids one of its biggest advantages. See mxdi9i7's answer for more info.

React - Create tag dynamically from ES6 template literal with JSX

I need to display a header element in a React render method where the level is dynamically set in the constructor:
class HeaderComponent extends React.Component {
constructor(props){
super(props);
this._checkedDepth = Math.min(6, props.depth)
}
render(){
return(<h{ this._checkedDepth }>{ this.props.name }</h{ this._checkedDepth }>)
}
}
ReactDOM.render(
<HeaderComponent name="Header 1" depth="2"/>,
document.getElementById('app')
);
<div id="app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
This should render <h2>Header 1</h2> with name="Header 1" and depth=2, but I get an error instead:
Uncaught Error: Cannot find module "./HeaderComponent"
What am I overlooking?
I'm using React 15.4.1, babel-preset-es2015 6.9.0, babel-preset-react 6.5.0 and running it in Chrome 55.
Each JSX element is just syntactic sugar for calling
React.createElement(component, props, ...children). So, anything you
can do with JSX can also be done with just plain JavaScript. -
https://facebook.github.io/react/docs/react-without-jsx.html
So you can do something like this:
render() {
return React.createElement(`h${this._checkedDepth}`, this.props)
}
Maybe a bit too late, but you can create a component or tag dynamically without using React.createClass with JSX putting the tag name in a variable and using that variable as you would with any other component.
In your case, inside render, you should have something like:
const TitleTag = `h{ this._checkedDepth }>`;
return <TitleTag>{ this.props.name }</TitleTag>
Note the first character of that variable must be uppercase in order to let React know that's a React component, otherwise a tag with the exact same name (not value) of your variable will be inserted instead.
See https://reactjs.org/docs/jsx-in-depth.html#user-defined-components-must-be-capitalized:
When an element type starts with a lowercase letter, it refers to a
built-in component like <div> or <span> and results in a string 'div'
or 'span' passed to React.createElement. Types that start with a
capital letter like <Foo /> compile to React.createElement(Foo) and
correspond to a component defined or imported in your JavaScript file.
We recommend naming components with a capital letter. If you do have a
component that starts with a lowercase letter, assign it to a
capitalized variable before using it in JSX.
There's no way to do this without creating that variable, so trying to do it on the fly as you do in your code will not work (compiler limitation).
Here's a fully working example:
class HeaderComponent extends React.Component {
constructor(props) {
super(props);
const depth = Math.max(Math.min(parseInt(props.depth) || 1, 6), 1);
this.state = { depth };
}
onClick() {
let depth;
do {
depth = Math.floor(Math.random() * 6) + 1;
} while(depth === this.state.depth);
this.setState({ depth });
}
render() {
const Title = `h${ this.state.depth }`;
return <Title className="title" onClick={ () => this.onClick() }>{ this.props.name }</Title>;
}
}
ReactDOM.render(
<HeaderComponent name="Click Me!" depth="1"/>,
document.getElementById('app')
);
body { margin: 0; }
h1 { font-size: 4rem; }
h2 { font-size: 3.5rem; }
h3 { font-size: 3rem; }
h4 { font-size: 2.5rem; }
h5 { font-size: 2rem; }
h6 { font-size: 1.5rem; }
.title {
margin: 0;
padding: 0 .5rem;
cursor: pointer;
user-select: none;
}
.title:hover {
background: #FFA;
}
<div id="app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

integrating js code inside react component

I have converted a component that displays chart bar, and it requires this js snippet to run, what is the correct way of integrating it inside my JSX code?
<script>
/** START JS Init "Peity" Bar (Sidebars/With Avatar & Stats) from sidebar-avatar-stats.html **/
$(".bar.peity-bar-primary-avatar-stats").peity("bar", {
fill: ["#2D99DC"],
width: 130,
})
</script>
I have seen this libraries on npm website, but they mostly deal with external scripts not internal
here is my component:
import React, { Component } from 'react';
export default class App extends Component {
render() {
return (
<div>
"How can I render js code here?"
</div>
);
}
}
You can use refs and componentDidMount callback in order to initialize jquery plugins, like so
class App extends React.Component {
componentDidMount() {
$(this.barChart).peity("bar", {
fill: ["#2D99DC"], width: 130
});
}
render() {
return <div>
<div ref={ (node) => { this.barChart = node } }>
<span class="bar">5,3,9,6,5,9,7,3,5,2</span>
<span class="bar">5,3,2,-1,-3,-2,2,3,5,2</span>
<span class="bar">0,-3,-6,-4,-5,-4,-7,-3,-5,-2</span>
</div>
</div>;
}
}
ReactDOM.render(
<App />,
document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/peity/3.2.1/jquery.peity.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container"></div>
You should use componentDidMount lifecycle hook.
Add this to your component code:
componentDidMount() {
$(".bar.peity-bar-primary-avatar-stats").peity("bar", {
fill: ["#2D99DC"],
width: 130,
})
}

Resources