how to go about with this Short circuit evaluation? - reactjs

I want to add PictureAlbums along with iframe. Basically, I'm trying to write like this: if timerStates is complete then render <iframe> and also PictureAlbum component.
With the code below I'm able to render only <PictureAlbums /> and not iframe. How do I solve this?
import React from 'react';
import PictureAlbums from './PictureAlbums';
import * as timerStates from './TimerState';
const lp = (val) => {
if (val < 10) return `0${val}`;
return `${val}`;
}
const TimerDisplay = (props) => (
<div>
<div>
{
(props.timerState === timerStates.COMPLETE)
&& <iframe src="https://www.youtube.com/"></iframe>
&& <PictureAlbums />
}
</div>
<div>
<h2>{`${lp(props.currentTime.get('hours'))}:${lp(props.currentTime.get('minutes'))}:${lp(props.currentTime.get('seconds'))}`}</h2>
</div>
</div>
);

You can use a React.Fragment for that to give both elements a common parent without inserting an extra element in the DOM.
{props.timerState === timerStates.COMPLETE && (
<React.Fragment>
<iframe src="https://www.youtube.com/"></iframe>
<PictureAlbums />
</React.Fragment>
)}

Related

How to print response Json data in jsx

I want to render title and description in jsx (Reside in data-->feed->title or Description)
also want to render each title and each pub date (Reside in data->items[array]->title and pub date)
import React,{useState,useEffect} from 'react'
import axios from 'axios';
function Dashboard(){
const[posts,setPosts] = useState([])
useEffect(()=>{
axios.get('https://api.rss2json.com/v1/api.json?rss_url=http%3A%2F%2Frss.cnn.com%2Fservices%2Fpodcasting%2Fstudentnews%2Frss.xml')
.then(res=> {
console.log(res)
setPosts(res.data)
})
.catch(err=>{
console.log(err)
})
},[])
return(
<div className="App">
</div>
)
}
may be you are trying to do something like this ?
return(
<div className="App">
<div> {posts.feed && posts.feed.title} </div>
<div> {posts.feed && posts.feed.description} </div>
<div>
{posts.items && posts.items.map ( postItem => <div> {postItem.title} </div> ) }
</div>
</div>
)
So first of all I suggest you to make your screens class components, than you can make your child components as functional components like above. So you can make a async function that make a request and fetches the data to the state.
Why you getting cannot read property of "title"?
Becouse when you load your component It's instantly looking for your posts array. Which is empty at the begining It need some time to make request and fill your array with the recieved data, that's why you getting this error I believe.
So just try it like following
{posts.length && post.map .... .... ...
Try it like :
return(
<div className="App">
{
(posts.items!==undefined && posts.items.length>0) && posts.items.map ( ele=> {
return (<div>{ele.title} - {ele.pubDate} </div> )})
}
</div>
)

Second layer of conditional statement within inline condition react

I am trying to check the trigger status if it is new, and after that i need to check another condition and based on which i need to display tagone or tagtwo.
I have been trying to find inline documentation for this.
<modalscrolling onClose={this.props.toggleModal} open={openModal}
trigger={isNew ?
<sometag /> :
<TagOne />}>
<TagTwp />}
>
the other approach i am trying is to send it to a different function. Any suggestions to deal with this :)
you can have nested ternary operators as following,
App.js
import React from "react";
import "./styles.css";
export default function App() {
var isNew = true;
var tag = 1;
return (
<div className="App">
{isNew ? (
tag === 1 ? (
<span>tag1</span>
) : (
<span>tag2</span>
)
) : (
<span>notnew</span>
)}
</div>
);
}
demo: https://codesandbox.io/s/ecstatic-shape-r64i8
but i would suggest extract inside teranary operation to another function component which takes "tag" as input. it helps to extend your code easily and make it more readable.
App.js with another after refactoring
import React from "react";
import "./styles.css";
const AnotherCompoent = ({ tag }) => {
return tag === 1 ? <span>tag1</span> : <span>tag2</span>;
};
export default function App() {
var isNew = true;
var tag = 1;
return (
<div className="App">
{isNew ? <AnotherCompoent tag={tag} /> : <span>notnew</span>}
</div>
);
}
demo: https://codesandbox.io/s/affectionate-hertz-1ou77
You can do something like this:
<modalscrolling onClose={this.props.toggleModal} open={openModal}
trigger={isNew ? <SomeTag /> : secondLevelCondition ? <TagOne /> :<TagTwp /> }
/>
Ternary operator is better option as it helps understand the component markup. If the conditional parts are big, convert them to seperate functional components.
trigger= { isNew ? <sometag/> : { anothercond ? <TagOne /> : <TagTwo/> }}.
Is this what you're looking for?

My Toaster component is not creating multiple toasters on multiple clicks. Reactjs

I have made a toaster component which is only rendering 1 toaster on 1 or multiple clicks, but I need a component the renders multiple toasters on multiple clicks.
This is my Toaster Component.
import React, {Component} from 'react'
import '../stylesheets/adminlte.css'
ToastMsg = (props) => (
<div className=" snackbar" key={props.idx}>
<div className="card-header">
<h3 className="card-title">Toast</h3>
</div>
<div className="card-body">{props.message}</div>
<div className="card-footer"/>
</div>
)
createtoaster = () => {
if (this.state.show) {
return this
.state
.message
.map((msg, idx) => <ToastMsg idx={idx} message={msg}/>)
} else {
return null;
}
}
render() {
return (
<div className="col-md-2 offset-md-9">
<button className="btn btn-primary" onClick={this.handleOpen}></button>
{this.createtoaster()}
</div>
)
}
I am providing this.state.message from another component and passsing it via props. I cannot use any Library as per the requirement so if anyone can help me with this, It is appreciated. Also feel free to point out any mistakes in my code.
missing array element 'picker': < div className="card-body">{this.state.message [i] }
I would use map, too ... with key property for each item.
Are you sure you're receiving array with more elements ?

How to hide TagNav in profile page in reactioncommerce

In reactionCommerce I want to hide TagNav in Navbar in profile component/page based on some condition. I am new into reactionCommerce
You need to override TagNav using Reaction Commerce's Component API.
Since you only want to customize the way the component is rendered, I suggest using getRawComponent to get Reaction's default TagNav component without its HOCs, then extending it and replacing it using replaceComponent.
import React from "react";
import { Components, getRawComponent, replaceComponent } from "#reactioncommerce/reaction-components";
const TagNav = getRawComponent("TagNav");
class CustomTagNav extends TagNav {
/**
* This implementation of render will override TagNav's default
*/
render() {
const { navbarOrientation, navbarPosition, navbarAnchor, navbarVisibility } = this.props;
// Provided that you want to return a whole different component tree if your condition matches
if (yourCondition) {
return (
{/* What you want to return if TagNav isn't shown */}
);
}
return (
<div className={`rui tagnav ${navbarOrientation} ${navbarPosition} ${navbarAnchor} ${navbarVisibility}`}>
<div className="navbar-header">
<Components.Button
primary={true}
icon="times"
status="default"
className="close-button"
onClick={this.props.closeNavbar}
/>
{this.props.children}
</div>
{this.renderShopSelect()}
<div className="navbar-items">
<Components.DragDropProvider>
<Components.TagList
{...this.props}
isTagNav={true}
draggable={true}
enableNewTagForm={true}
>
<div className="dropdown-container">
<Components.TagGroup
{...this.props}
editable={this.props.editable === true}
tagGroupProps={this.tagGroupProps(this.state.selectedTag || {})}
onMove={this.props.onMoveTag}
onTagInputBlur={this.handleTagSave}
onTagMouseOut={this.handleTagMouseOut}
onTagMouseOver={this.handleTagMouseOver}
onTagSave={this.handleTagSave}
/>
</div>
</Components.TagList>
</Components.DragDropProvider>
{this.props.canEdit && this.renderEditButton()}
</div>
</div>
);
}
}
replaceComponent("TagNav", CustomTagNav);

React conditional rendering bug even with single parent and child list [duplicate]

This question already has answers here:
How can I return multiple lines JSX in another return statement in React?
(8 answers)
Closed 4 years ago.
Learning a bit of React but it seems to me like there's a conditional rendering bug with React itself.
Suppose I have a Foo component like so:
foo.js
import React, { Component } from 'react';
class Foo extends Component {
render() {
const isLoggedIn = this.props.isLoggedIn;
return(
<div>
{ isLoggedIn ? (
<div>one</div><div>two</div>
) : (
<div>one</div><div>two</div><div>three</div>
)}
</div>
);
}
}
export default Foo;
and I use it like so:
app.js
import React, { Component } from 'react';
import Foo from './components/foo';
class App extends Component {
render() {
return (
<div>
<Foo isLoggedIn={false} />
</div>
);
}
}
export default App;
This produces the error:
Syntax error: Adjacent JSX elements must be wrapped in an enclosing tag
Please note the above Foo component, there is only a single parent div being returned not array. If it was an array, then yes I agree with the error.
The official example given in the React document's example is like this:
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
{isLoggedIn ? (
<LogoutButton onClick={this.handleLogoutClick} />
) : (
<LoginButton onClick={this.handleLoginClick} />
)}
</div>
);
}
https://reactjs.org/docs/conditional-rendering.html
Does this look like a bug in React to anyone?
Update
Based on the answers and comments given here, the implied behaviour of React is ternary operators inside the render() function comes with it's own render calls behind the scenes, acting like a virtual component, which would mean an extra layer of <div> needs to be wrapped around the list of my child elements.
Emberjs Foo component
My confusion arise from the fact I have done some Emberjs development in the past and a component like this works as expected:
<h3>Foo component</h3>
{{#if isLoggedIn}}
<div>one</div><div>two</div>
{{else}}
<div>one</div><div>two</div><div>three</div>
{{/if}}
Thanks for the explanation from everyone nonetheless.
You are returning the 2 or 3 divs in the condition. Instead you should wrap them into on div and return.
Notice the wrapper div below.
{ isLoggedIn ? (
<div className='wrapper'><div>one</div><div>two</div><div>
) : (
</div className='wrapper'><div>one</div><div>two</div><div>three</div></div>
)}
Also note that there is small typo below
<div>one</div><div>two</div><div>three</div
You have a syntax error
<div>one</div><div>two</div><div>three</div
should be
<div>one</div><div>two</div><div>three</div>
Did you try adding ?
return(
<div>
{ isLoggedIn ? (
<Fragment><div>one</div><div>two</div><Fragment>
) : (
<Fragment><div>one</div><div>two</div><div>three</div><Fragment>
)}
</div>
);
Syntax error: Adjacent JSX elements must be wrapped in an enclosing tag?
you are returning multiple sibling JSX elements in an incorrect manner.
In Foo:
return(
<div>
{ isLoggedIn ? (
<div>one</div> //are siblings without
<div>two</div> //wrapping in container element.
) : (
<div>one</div> //are siblings without
<div>two</div> //wrapping in
<div>three</div>//container element.
)}
</div>
);
Right approach :
return (
<div>
{isLoggedIn
? (
<div> //add wrapper
/...
</div>
)
: (
<div> //add wrapper
//...
</div>
)}
</div>
);
Or
If you are using React16 then you can use React.Fragement as well:
e.g.
<React.Fragment>
<div>one</div>
<div>two</div>
</React.Fragment>
You need to wrap the element rendered in the condition
return(
<div>
{ isLoggedIn ? (
<div><div>one</div><div>two</div></div>
) : (
<div><div>one</div><div>two</div><div>three</div></div>
)}
</div>
);
Note the extra div around the nested conditional elements

Resources