How to add classes to dynamically created elements in React JS? - javascript

{temp_array_beg.map((el,index) => (
<div key={index} className="subRenderButton">
<input type="button" value={el.i} className="paginationBtn" onClick= {this.handlePaginationClick.bind(this)} />
</div>
))}
Ihave tried Conditional Rendering of class but then all the rendered divs got the active class

{temp_array.map((btn,index) => (
<div key={index} className="subRenderButton">
<input type="button"value={btn.i} className={["paginationBtn",buttonNumber == btn.i ? "active" :""].join(' ')} onClick={this.handlePaginationClick.bind(this)} />
</div>
))}
I have managed to solve the problem Thanks!

Related

Re-ordering JSX including React's Context Provider

I'm wondering if there is a way of re-factoring this code so that RepeatableAttributeSetContextProvider does not wrap all of the JSX elements but sits above them (so opens and closes before StyledHorizontalAttributesTable). When I do that at present, then values like enteredObject: "cannot be defined".
I want to try this so that I can decouple of some of the JSX that comes along with RepeatableAttributeSetContextProvider (such as labels) away from the rest of my JSX (to sit on top instead of wrap) Any ideas would be great!
return (
<div className={className}>
{objects.map((enteredObject, index) => (
<RepeatableAttributeSetContextProvider
form={form}
object={enteredObject}
key={`${enteredObject.key}-${enteredObject.repeatIndex}`}
>
<StyledHorizontalAttributesTable className="attributeset-row">
{enteredObject.attributeCollection.questions
.filter(filterRepeatAttributes)
.map((attribute) => (
<Fragment key={attribute.key}>
{renderAttribute(enteredObject, attribute, formLayout)}
</Fragment>
))}
<StyledButton
className="remove-btn"
type="link"
buttonStyle="LINK"
name="delete"
dataId={`delete-${enteredObject.key}-${index}`}
icon="bin"
onClick={() => onRemove(enteredObject)}
>
<Message id="Form.Button.Remove" defaultMessage="Remove" />
</StyledButton>
</StyledHorizontalAttributesTable>
</RepeatableAttributeSetContextProvider>
))}
</div>
);
Do you mean something like
return (
<div className={className}>
{objects.map((enteredObject, index) => (
<>
<RepeatableAttributeSetContextProvider
form={form}
object={enteredObject}
key={`${enteredObject.key}-${enteredObject.repeatIndex}`}
/>
<StyledHorizontalAttributesTable className="attributeset-row">
{enteredObject.attributeCollection.questions
.filter(filterRepeatAttributes)
.map((attribute) => (
<Fragment key={attribute.key}>
{renderAttribute(enteredObject, attribute, formLayout)}
</Fragment>
))}
<StyledButton
className="remove-btn"
type="link"
buttonStyle="LINK"
name="delete"
dataId={`delete-${enteredObject.key}-${index}`}
icon="bin"
onClick={() => onRemove(enteredObject)}
>
<Message id="Form.Button.Remove" defaultMessage="Remove" />
</StyledButton>
</StyledHorizontalAttributesTable>
</>
))}
</div>
);
But then you obviously won't have any access to the (assumed) context provided by RepeatableAttributeSetContextProvider. If you do need it, then you do need to wrap your JSX within it. If you don't need it, then why have the component at all?

How can I style map items to display in justify-content-around?

I'm looping through products by mapping them and the justify-content-around doesn't apply to them and I'm using bootstrap 4 in my react project .
Here is my code :
{props.products.map((item) => {
if (item.inCart) {
return (
<div className="d-flex justify-content-around w-100" key={item.id}>
<button>remove</button>
<div>
<h5>{item.name}</h5>
</div>
<div>
<h5>{item.price.toLocaleString('ar-EG')}</h5>
</div>
<div>
<h5>{item.number.toLocaleString('ar-EG')}</h5>
</div>
<div>
<h5>{(item.number * item.price).toLocaleString('ar-EG')}</h5>
</div>
<hr />
</div>
);
}
The display flex class applies but not the other one and they all have no margin between them .
How can I make them to display justify-content-around ??
Your problem come from the <hr> tag. I just discovered it by doing this repro on stackblitz. Remove it and it works.
If you readlly need it then just receate it:
const Divider = () => {
return <div className="border-bottom" />;
};
This one is bootstrap dependant but of course you can make it generic easily. You just need to apply it outside of your flex container :
<>
<div className='d-flex justify-content-around' key={item.id}>
<button>remove</button>
<h5>{item.name}</h5>
<h5>{item.name}</h5>
<h5>{item.name}</h5>
</div>
<Divider />
</>;

How can I render multiple elements after an inline condition using short circuit evaluation?

Using a short circuit evaluation in a functional component (with hooks):
const Filters = () => {
const [options, setOptions] = useState([]);
return (
<div className="row">
{options.length > 0 && (
<div className="col-md-3">
<CustomComponent />
</div>
)}
</div>
)
}
Is there a way to render multiple elements right after an inline if condition?
{options.length > 0 && (
<div className="col-md-3">
<CustomComponent />
</div>
<div className="col-md-3">
<SecondComponent />
</div>
)}
Code above doesn't work, react throws an error. options array is filled after a promise resolved from useEffect(). That's why i've added this check, to display elements only when a promise resolved.
UPDATED CODE for #wentjun:
return (
{options.length > 0 && (
<div className="row">
<div className="col-md-3">
<CustomComponent />
</div>
</div>
)}
)
This throws a syntax error.
I think the error is due to returning two react elements. Try wrapping then in fragment
{options.length > 0 && (
<>
<div className="col-md-3">
<CustomComponent />
</div>
<div className="col-md-3">
<SecondComponent />
</div>
</>
)}
You should wrap the elements in React Fragments. The reason being, React elements are rendered via a single root node element. Wrapping it in Fragments will allow you to group the elements without adding additional nodes.
return (
<div className="row">
{options.length > 0 && (
<>
<div className="col-md-3">
<CustomComponent />
</div>
<div className="col-md-3">
<SecondComponent />
</div>
</>
)}
</div>
)

How to make images fit the page in React/Bootstrap?

I am using a function that maps every item in the props array to creating an image tag. I am trying to make every 3 images have a row div around them using bootstrap so they will fit the page correctly, but I cannot figure out how to do it. Any help would be appreciated. Here is the code:
import React, { Component } from 'react';
import "./Skills.css";
export default class Skills extends Component {
static defaultProps = {
images: [
"https://upload.wikimedia.org/wikipedia/commons/thumb/6/61/HTML5_logo_and_wordmark.svg/1200px-HTML5_logo_and_wordmark.svg.png",
"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/CSS3_logo_and_wordmark.svg/1200px-CSS3_logo_and_wordmark.svg.png",
"https://upload.wikimedia.org/wikipedia/commons/6/6a/JavaScript-logo.png",
"https://p7.hiclipart.com/preview/306/37/167/node-js-javascript-web-application-express-js-computer-software-others.jpg",
"https://bs-uploads.toptal.io/blackfish-uploads/skill_page/content/logo_file/logo/5982/express_js-161052138fa79136c0474521906b55e2.png",
"https://webassets.mongodb.com/_com_assets/cms/mongodb_logo1-76twgcu2dm.png",
"https://www.pngfind.com/pngs/m/430-4309307_react-js-transparent-logo-hd-png-download.png",
"https://botw-pd.s3.amazonaws.com/styles/logo-thumbnail/s3/012015/bootstrap.png?itok=GTbtFeUj",
"https://sass-lang.com/assets/img/styleguide/color-1c4aab2b.png"
]
}
photo() {
return (
<div >
{this.props.images.map(image => (
<div className="col-md-4">
<img className="photo" src={image} />
</div>
))}
</div>
);
}
render() {
return (
<div id="skills-background" className="mt-5">
<div id="skills-heading" className="text-center">Skills I've Learned:</div>
<div className="container">
<div className="row">
{this.photo()}
</div>
</div>
</div>
)
}
}
CodeSandbox
I think, I found the issue,
<div> <-----This div is the issue
{this.props.images.map(image => (
<div className="col-md-4">
<img className="photo" src={image} />
</div>
))}
</div>
You have wrapped your col-md-4 with a div, and div has display: block style, so you are getting every image on separate row. Simply replace div with Fragments,
<> <-----Make it Fragment
{this.props.images.map(image => (
<div className="col-md-4">
<img className="photo" src={image} />
</div>
))}
</>

React mouseEnter event not working when on mapped children

I just want these child elements to show a remove button on mouseover...
console logging in handleMouseEnter shows that on render, ALL children fire the mouseEnter event. it seems stuck in a loop. debugging is next to impossible.
problems only arise when onMouseEnter and onMouseLeave are left in the code.
render(){
const handleMouseEnter = (tool) => this.setState({display : tool});
const handleMouseLeave = () => this.setState({display : "none"});
return (
<div>
<div className="search-result-background">
<div className="search-result-row row">
<div className="col-md-4">
</div>
<div className="col-md-4">
<form>
<TextFieldGroup className="find-tool-search-bar"
onChange= {this.checkToolExists}
value = {this.state.toolname}
field = 'toolname'
label = ''
error = {this.state.errors}
placeholder = "FIND IN FAVORITES"
/>
</form>
</div>
<div className="col-md-4">
<ButtonToolbar>
<DropdownButton noCaret onSelect={this.sort} bsSize="large" title="Sort by" id="dropdown-size-large">
<MenuItem eventKey="1">Name</MenuItem>
<MenuItem eventKey="2">Uploaded Date</MenuItem>
</DropdownButton>
</ButtonToolbar>
</div>
<h1 className="search-error">{this.state.errors}</h1>
<div className="col-md-12" >
{this.state.filteredTools.map((tool,i)=>
<div key ={i} className={"child " + tool.toolname } onMouseEnter={handleMouseEnter(tool.toolname)}
onMouseLeave={handleMouseLeave}> {this.state.display == tool.toolname ?
<button >remove?</button> : null}
<Link to={`/tools/${tool.id.substring(4)}`}>
<Thumbnail
className="thumb" src={logoImagePurple} alt="242x200">
<h3>{tool.toolname}</h3>
</Thumbnail>
</Link>
</div>
)}
</div>
</div>
</div>
</div>
)
}
}
The problem is this line:
onMouseEnter={handleMouseEnter(tool.toolname)}
You should change it to:
onMouseEnter={() => handleMouseEnter(tool.toolname)}

Categories