JSX add attribute to array of different objects - javascript

I have a page with a bunch of sub-pages:
render(){
let elements = [<Apple>,<Orange>,<Pear>];
return <div>
{Elements}
</div>
}
I want to give each of these elements the same property, e.g. color:
render(){
let elements = [<Apple>,<Orange>,<Pear>];
elements.forEach(i=>i.setAttribute('color','blue')); //???
return <div>
{Elements}
</div>
}
So that it would be equivalent to:
render(){
return <div>
<Apple color='blue'/>
<Orange color='blue'/>
<Pear color='blue'/>
</div>
}
How would I do this?

Fix your elements to
let elements = [Apple, Orange, Pear];
then use array map to pass a common prop.
render() {
let elements = [Apple, Orange, Pear];
const elementsWithColorBlue = elements.map((Element) => (
<Element color="blue" />
));
return <div>{elementsWithColorBlue}</div>
}

An alternate way of writing than the answer above would be as below
render(){
return (
<div>
{[Apple, Orange, Pear].map(Element => <Element color="blue" />)}
</div>
)
}

Related

I have a component I want to appear once the timer is done

I have my component CountDownSquare I want to disappear once the timer is done fully counting down. I have Data in homePageData that holds the main text in a h3 element, this text should appear once the timer is fully done. Here's a ternary statement I attempt to assign but it isn't assigned to anything the way I thought it would be. Here is a snippet of what I thought of
const { homePageData } = props;
{homePageData[0].showCountdown ? <CountDownSquare/>: styles.homeBody}
return (
homePageData && (
<Layout>
<div className={styles.Home}>
<Image src={wordmark} alt="Hammer and Hope wordmark" />
<CountDownSquare >
</CountDownSquare>
{/* <div className={styles.homeBody}>
<h3 className={styles.mainText}>{homePageData[0].mainText}</h3> */}
<Nav />
</div>
</Layout>
)
);
} ```
I am assuming homePageData[0].showCountDown is a boolean which is true if the countdown is complete in the parent component.
You need to add conditions while rendering your component.
The following snippet will render the CountDownSquare component and the h3 tag with homePageData[0].mainText if homePageData[0].showCountdown is true.
const { homePageData } = props;
return (
homePageData ?? (
<Layout>
<div className={styles.Home}>
<Image src={wordmark} alt="Hammer and Hope wordmark" />
{homePageData[0].showCountdown ??
<CountDownSquare >
</CountDownSquare>
<div className={styles.homeBody}>
<h3 className={styles.mainText}>{homePageData[0].mainText}</h3>
</div>
}
</div>
</Layout>
)
);

How to add a React component to a loop?

I have data stored in an object and I want to loop through the data and set it as the props for my component.
My component is a card, and I want to show a card for every piece of data in the loop.
This is code so far -
function App() {
let title = [];
for (let key in projectDataObject) {
let newObj = projectDataObject[key].sites;
for (let key in newObj) {
title = newObj[key].title;
}
return (
<div className="App">
<header className="App-header">
<Card title={title}></Card>
</header>
</div>
);
}
}
export default App;
The problem here is because of the "return" it stops the loop at the first item, and does not loop through everything else.
How can I do this?
use it like this:
<div className="App">
<header className="App-header">
{Object.keys(yourObject).map(function(key) {
return <Card title={yourObject[key].title} />;
})}
</header>
</div>
This code doesn't make any sense. You're just taking the last one as the title, so looping is pointless.
for (let key in newObj) {
title = newObj[key].title;
}
Since I can't really tell what you're trying to do there, I'll make an assumption to get you pretty close. It looks like you're trying to pull out all of the titles from your object graph, so let's do that first.
function App() {
const titles = /* I can't tell what your data structure is,
so flatten it to get all of the titles out and into an array here */
return (
<div className="App">
<header className="App-header">
{/* this will put a list of cards in the header */}
{titles.map(title => <Card title={title}/>)}
</header>
</div>
);
}
}
export default App;

How to render conditional with classNames with Reactjs

I am trying to use classNames to replace the conditional below in one line.
My problem is that i am not sure what is the right way to write the code because of the div etc...
I have the codes below :
conditional
const { pageTitle, removeTitle = false } = props; # destructuring
let result;
if(removeTitle){
result = <div className="header-without-title">{pageTitle}</div>;
} else {
result = <div className="header-with-title">{pageTitle}</div>;
}
return (<div className="result-title">{result});
};
If the div did not exist, i could write something like this...
const result = classNames({"header-without-title": removeTitle, "header-title": !removeTitle});
But i am not sure now that I have the div , I would appreciate some help here...
A solution outside of JSX would be very helpful
return (
<div className="result-title">
<div className={`header-${removeTitle ? 'without-title' : 'with-title'}`}>{pageTitle}</div>
</div>
);
or with use https://github.com/JedWatson/classnames
return (
<div className="result-title">
<div className={classNames({ 'header-without-title': removeTitle, 'header-with-title': !removeTitle })}>
{pageTitle}
</div>
</div>
);
EDIT:
A solution outside of JSX
const result = (
<div className={classNames({ 'header-without-title': removeTitle, 'header-with-title': !removeTitle })}>
{pageTitle}
</div>
);
return (
<div className="result-title">
{result}
</div>
);
You can just inline classNames function
const { pageTitle, removeTitle = false } = props;
const result = classNames({"header-without-title": removeTitle, "header-title": !removeTitle});
return (
<div className="result-title">
<div className={result}>
{pageTitle}
</div>
</div>);
);
There are several answers to this. Depends of each case
Ternary between two classes in React:
<div className={`header-${removeTitle ? 'without-title' : 'with-title'}`}>
Ternary between class or null in React Javascript:
<div className={removeTitle ? 'without-title' : null}>
Ternary between render class or not in React Javascript and Typescript:
<div className={...(removeTitle ? { className: 'without-title' } : {})}>

How to get value from contentEditable in reactjs

I'm fairly new to ReactJS. I am looking to get the value inside a <div> when contentEditable is set to true.
const listResults = this.state.results['1'].map((result) =>
<div key={result.toString()} contentEditable="true">
{result}
</div>
);
return (
<h1> listResults </h1>
<div> {listResults} </div>
)
I am currently outputting a list into pre-filled text-boxes which allows the user to edit them. I am looking to add in a button which once clicked captures the data inside all of the text-boxes. Can anyone point me in a direction on how to capture the changed data.
It may also be worth noting I am using ReactJS on the client side through a CDN.
To get value of editable div:
class App extends React.Component {
constructor(){
super();
this.state = {
arr: [1,2,3,4,5]
}
this.change = this.change.bind(this);
}
change(e, index){
let tmpArr = this.state.arr;
tmpArr[index] = e.target.textContent;
this.setState({arr: tmpArr})
}
render(){
console.log(this.state);
return (
<tr>
{this.state.arr.map((el, index) => <td key={index} id="test" onBlur={(e) => this.change(e, index)} contentEditable="true">{el}</td>)}
</tr>
);
}
}
https://jsfiddle.net/69z2wepo/84647/
One note, you can't return two elements on the same level:
return (
<h1> listResults </h1>
<div> {listResults} </div>
)
It should be wrapped like this:
return (
<div>
<h1> listResults </h1>
<div> {listResults} </div>
</div>
)

I think this is another React/JS context issue, how do I extract this variable?

I have an array[] of tracks that I receive from an API.
I pass it to a map function which will return a track for every track in tracks. I want to export a variable (Song) specific to that track to be be processed in my event handler as such. The only thing thats not working is the scope of song. I cant set the state of song in my map function or the component goes into an infinite rerender loop.
handleEnter(){
//I want to get the song into this context and play it here
this.props.mouseEnter();
}
handleLeave(){
//same for pausing
this.props.mouseLeave();
}
createTrack(track){
var song = new Audio([track.preview_url]);
return (
<div className="image" key={track.id}>
<img
className="img-circle"
src={track.album.images[0].url}
onMouseEnter={this.handleEnter.bind(this)}
onMouseLeave={this.handleLeave.bind(this)}
/>
<p className="showMe"><span>{track.name}</span></p>
</div>
);
}
getTracks(){
if(this.props.tracks) {
console.log(this.props.tracks);
return (
<div>{this.props.tracks.map(track => this.createTrack(track))}</div>
);
}
}
componentWillMount(){
this.props.fetchMessage();
}
render(){
return(
<div>{this.getTracks()}</div>
)
}
if you want to use .bind, you can send it to handleEnter and handleLeave.
handleEnter( trackID ) {
// trackID available here
}
createTrack(track){
var song = new Audio([track.preview_url]);
return (
<div className="image" key={track.id}>
<img
className="img-circle"
src={track.album.images[0].url}
onMouseEnter={this.handleEnter.bind( this, track.id )}
onMouseLeave={this.handleLeave.bind( this, track.id )}
/>
<p className="showMe"><span>{track.name}</span></p>
</div>
);
}
It's typically best practice to not use .bind in react since it creates a new function on every render. Rather, you should create a <Track /> component, pass it the track, then pass handleEnter and handleLeave as props.
const track = ( props ) => {
let { track, handleEnter, handleLeave } = props;
const onMouseEnter = () {
handleEnter( track.id );
}
const onMouseLeave = () {
handleLeave( track.id );
}
return (
<div className="image" key={track.id}>
<img
className="img-circle"
src={track.album.images[0].url}
onMouseEnter={ onMouseEnter }
onMouseLeave={ onMouseLeave }
/>
<p className="showMe">
<span>{track.name}</span>
</p>
</div>
);
};
then in your render, you'd map like you're doing and output <Track /> pure components instead of full-on components
Have a look at this. Hopefully it will solve your problem.
handleEnter(track, e){
// you will get the full track object and use the data
this.props.mouseEnter();
}
handleLeave(track, e){
// you will get the full track object and use the data
this.props.mouseLeave();
}
componentWillMount(){
this.props.fetchMessage();
}
render(){
const createTrack = (track, index) => {
var song = new Audio([track.preview_url]);
return (
<div className="image" key={'track-'+ index}>
<img
className="img-circle"
src={track.album.images[0].url}
onMouseEnter={this.handleEnter.bind(this, track)}
onMouseLeave={this.handleLeave.bind(this,track)}
/>
<p className="showMe"><span>{track.name}</span></p>
</div>
);
}
return(
<div>{this.props.tracks ? this.props.tracks.map(createTrack) : null }</div>
)
}

Categories