I have a templates.js file where i set values manually:
export const galleries = [{name:'default'},{name:'carousel'},{name:'grid',set:true}];
If object contain {set:true} I want to render a specific component on product.js page.
I was thinking at:
const gallery = galleries.find(gallery=>gallery.set==true).name
then render:
<div>
gallery == "grid" ? (
<Grid />
) : gallery == "carousel" ? (
<Carousel />
) : (
<Default />
)
</div>
But it's a little messy...
Is there a better aproach or is there already a package that did this?
const Component = {
grid: <Grid />,
carousel: <Carousel />,
default: <Default />
}
Option 1:
render:
<div>
{Component[gallery]}
</div>
Option 2:
I recommend you to validate gallery because the find function may returns null:
const item = galleries.find(gallery=>gallery.set==true);
const gallery = item ? item.name : "default";
then:
<div>
{Component[gallery]}
</div>
Related
Unable to render images in react, In browser console, image names are displayed correctly but on UI it is not displayed. Also, src attribute is missing from img tag after inspecting element. Please assist. Here is Sample Script
function importAll(r) {
let images = {};
r.keys().map((item, index) => { images[item.replace('./', '')] = r(item); });
return images;
}
const get_images = importAll(require.context('../../images', true, /\.(png|jpe?g|svg)$/));
const images = Object.entries(get_images).map(module => module[1].default);
return (
<div className="product">
<div>
<Row>
{products.map(product =>
<Col span={6} key={product.productId}>
<div >
<div>{console.log(product.productImageName)}
{<Image src={images[product.productImageName]} width={200}
height={200} />}
</div>
</div>
</Col>
)
}
</Row>
</div>
</div>
)
You don't need to import images. if images are part of your repository then you can use the relative path from the src directory. e.g assuming the images in under src
const path = `images/${[product.productImageName]}`;
<Image src={path} />
You should try and check if profile exist. Like this:
{profile && profile.map((...
//Or
{profile?.map((...
Within the same file, I'm having an element (or group of elements) that I want to convert to something reusable. But because it is very small, I don't want to create a new file.
Ex.
// Article.js
const Article = props => {
const { name, tel } = props
return (
<div>
<section>
<p>Content A</p>
<small>Contact {name} now, via {tel}</small>
</section>
<small>Contact {name} now, via {tel}</small>
<div>
Having questions?
<small>Contact {name} now, via {tel}</small>
</div>
</div>
)
}
As you can see here, <small>Contact {name} now, via {tel}</small> is being used many times in Article component. So I want to convert it to something reusable, either a Component or just a JSX element.
The key points are:
I do not want to create a new file, because it will never being used by other components.
It needs to display content depending on name and tel variables.
It does not need to be flexible, the name and tel will always be the same as from Article props.
So I tried to achieve my goal with:
Option 1: Separated React Component (in the same file)
// Article.js
const Contact = props => {
const { name, tel } = props
return <small>Contact {name} now, via {tel}</small>
}
const Article = props => {
const { name, tel } = props
return (
<div>
<section>
<p>Content A</p>
<Contact name={name} tel={tel}/>
</section>
<Contact name={name} tel={tel}/>
<div>
Having questions?
<Contact name={name} tel={tel}/>
</div>
</div>
)
}
But from my key point number 3, I find this option redundant because I have no need to make Contact accepting props. Since this component will always display the same name and tel as from Article. So I come up with Option 2.
Option 2: React Component in React Component
// Article.js
const Article = props => {
const { name, tel } = props
const Contact = () => (
<small>Contact {name} now, via {tel}</small>
)
return (
<div>
<section>
<p>Content A</p>
<Contact />
</section>
<Contact />
<div>
Having questions?
<Contact />
</div>
</div>
)
}
The Contact component is shorter because it accepts no props. But the question is if it does not accepting props, shouldn't I just write it as a JSX element? So I come up with Option 3.
Option 3: JSX Element in React Component
// Article.js
const Article = props => {
const { name, tel } = props
const renderContact = <small>Contact {name} now, via {tel}</small>
return (
<div>
<section>
<p>Content A</p>
{renderContact}
</section>
{renderContact}
<div>
Having questions?
{renderContact}
</div>
</div>
)
}
This one I don't know how to name it properly (renderContact, contactElement, or contact?) because I have not seen it much.
Every option is working, but I want to know the differences between these styles,
Performance - how does each one work / how does it affect the perf?
Pros and Cons
Limitations - is there anything to worry when using it?
Popularities - what is the standard way of writing React?
In this situation we write a reusable function usually called renderer
const Article = props => {
const { name, tel } = props
const renderer=(name,tel)=>{
return (
<small>Contact {name} now, via {tel}</small>
)
}
return (
<div>
<section>
<p>Content A</p>
{renderer(name,tel)}
</section>
</div>
</div>
)
}
I have a react component that allows a user to click a button in the header and add different input types.
export default class ElementContainer extends Component {
render() {
return (
<div className="append-header">
<Headline buttonCheck={this.props.buttonCheck} />
<SubHeadline buttonCheck={this.props.buttonCheck} />
<URLButton={this.props.buttonCheck} />
</div>
)
}
}
I'm trying to implement react-beautiful-dnd into the project so that those inputs can be repositioned like a list in Trello.
Looking at that library (and other similar libraries), they use the data as lists in order to perform the drag and drop function.
The items in my app are added to the view by conditional rendering:
export default class InputShow extends Component {
render() {
const { node } = this.props;
return (
<div className="editor-div" >
{
(node.type === 'buttonA') ?
<textarea
//omitted code
id={node.id}
onChange={this.props.inputContentHandler} />
:
(node.type === 'buttonB')
?
<URLButton
url={this.url}
id={node.id}
title={this.title}
/>
:
""
}
</div >
)
}
}
I've tried to map the items by creating a state for items (additions)
export default class InputShow extends Component {
constructor(props) {
super(props)
this.state = {
additions: []
}
}
render() {
const { node } = this.props;
return (
<div className="editor-div" >
{this.state.additions.map(addition => (
<div key={addition.id}>
{
(node.type === 'buttonA') ?
<textarea
//omitted code
id={node.id}
onChange={this.props.inputContentHandler} />
:
(node.type === 'buttonB')
?
<URLButton
url={this.url}
id={node.id}
title={this.title}
/>
:
""
}
</div>
))}
</div >
)
}
}
I didn't get any errors, however now when I click on the buttons, no data is being displayed in the view. I've done simple maps in the past with API and local data but I've never tried it with ternary statements. Thanks for any feedback on a solution to this problem.
What you can do is separate the view logic from the code and create a functional component. Pass the values from the main as below:
{this.state.additions.map(addition => (
return <CustomTemplate id={addition.id}
nodeId={node.id} changeEvent={this.props.inputContentHandler}
nodeType={node.Type} url={this.url} title={this.title}/>))}
Create CustomTemplate something like this
const CustomeTemplate =(props)=>(
use props to get the values in the templates
)
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>
)}
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);