How to put classname and variables in ternary at Reactjs? - javascript

I have different datasets. Some of them have only icon and some of them have images. I want to control the data whether iconurl is null or not in the beginning and then if has icon url I will use FontAwesome if iconurl = null I will use img tag. But my images does not come to screen. Also I have could not bring the name to h3 tag. It looks empty on the screen. I am confused a bit. May you help me please? thank you in advance.
Note: I have already checked some ternary examples in react but they were too basic.
render() {
return (
this.state.diagnoses.map(user =>
<div className={'cat-box-region'}>
<div className={'cat-box-position'}>
<div className={'cat-box'}>
{user.IconUrl ? (<FontAwesomeIcon icon={user.IconUrl} size="3x" className={'icon'}/>) : (<img src={user.ImgUrl} className={'ultrasound-img'}/>)}
<h3>{user.name}</h3>
</div>
</div>
</div>
)
);
}

I solved problem like that :
class DiagnosisBox extends Component {
static propTypes = {};
state = {
diagnoses: [],
diagnosesWithImg: [],
diagnosesWithIcon: []
};
componentDidMount() {
fetch('http://localhost:51210/api/service')
.then(response => {
return response.json();
}).then(diagnoses => {
this.setState({
diagnoses,
});
console.log(diagnoses);
})
}
render() {
this.state.diagnoses.map(stateData =>
stateData.iconUrl ? this.state.diagnosesWithIcon.push(stateData)
: this.state.diagnosesWithImg.push(stateData)
);
return (
<div className={'cat-box-region'}>
{this.state.diagnosesWithIcon.map(data =>
<div key={data.id} className={'cat-box-position'}>
<div className={'cat-box'}>
<FontAwesomeIcon icon={data.iconUrl} size="3x" className={'icon'} />
<h3>{data.diagnosisName}</h3>
</div>
</div>
)}
{this.state.diagnosesWithImg.map(data =>
<div key={data.id} className={'cat-box-position'}>
<div className={'cat-box'}>
<img src={data.ImgUrl} className={'ultrasound-img'}/>
<h3>{data.diagnosisName}</h3>
</div>
</div>
)}
</div>
);
}
}
export default DiagnosisBox;

Related

react-responsive-carousel messed up

I've read the documentation, I don't know why it's working but it's messed up. Here's my code :
function CarouselItem(props) {
const { post } = props
return (
<React.Fragment>
<div>
<img src={`http://localhost:5000/image/${post.foto}`} />
<p className="legend">{post.judul}</p>
</div>
</React.Fragment>
)
}
function NewsItem(props) {
const { posts } = props.post
let content = posts.map(item => <CarouselItem key={item._id} post={item} />)
return (
<div>
<Carousel showThumbs={false}>{content}</Carousel>
</div>
)
}
It turns out like this :
Use this in the first line of your .js file:
import 'react-responsive-carousel/lib/styles/carousel.min.css';

How to fix error of hiding and showing <div> in React

I am working on a project and i want to display a hidden <div> below another <div> element using an event handler but when i click the icon that is meant to display the div, the whole page becomes blank
This is image I want:
This is what i get
I have tried to check through the internet for some places where i could get the solution. Well i found something similar to what i had done but the error still happens for me.
class PostItTeaser extends Component {
state = {
postIt: false,
moreIt: false,
}
togglePostIt = e => {
e ? e.preventDefault() : null
this.setState({ postIt: !this.state.postIt })
}
_toggle = e => {
e ? e.preventDefault() : null
this.setState({
moreIt: !this.state.moreIt,
})
}
Child = () => <div className="modal">Hello, World!</div>
render() {
let { postIt } = this.state
let { moreIt } = this.state
let {
type,
group,
disabled,
session: { id, username },
} = this.props
return (
<div>
<div
className="post_it inst"
style={{ marginBottom: type == 'group' && 10 }}
>
<img src={`/users/${id}/avatar.jpg`} alt="Your avatar" />
<div className="post_teaser">
<span
className="p_whats_new"
onClick={disabled ? null : this.togglePostIt}
>
What's new with you, #{username}? #cool
</span>
<span className="m_m_exp" data-tip="More" onClick={this._toggle}>
<MaterialIcon icon="expand_more" />
</span>
</div>
</div>
{moreIt && <Child />}
{postIt && (
<PostIt back={this.togglePostIt} type={type} group={group} />
)}
</div>
)
}
}
From skimming through the code I believe you need to bind the scope, since the function you're calling is using this.setState, it needs this to be the react component, not the event you're listening to:
onClick={this._toggle.bind(this)}
You can also bind the functions scope in the constructor. Or, a less memory performant & ugly way:
onClick={() => { this._toggle(); } }

Conditional rendering on React.js

render() {
const tableStyle = this.getTableStyle();
const tableSettings = this.getTableSettings();
return (
<div style={tables}>
<TablePosition
contextMenuOn={true}
step={this.props.step}
pdfData={this.props.pdfData}
tableSettings={tableSettings}
tableStyle={tableStyle}
fileName={this.state.fileName}
tableSize={this.getTableSize()}
tableOffset={this.state.tableOffset}
desiredWidth={700}
updateXOffset={x => this.updateXOffset(x)}
updateYOffset={y => this.updateYOffset(y)}
markTable={() => this.markTable()}
setOutputLabels={(row, col, val) => this.setOuputLabels(row, col, val)}
/>
</div>
);
if (!this.props.isThirdStep) {
return (
<div>
<div style={sideBySide}>
<PDFViewer
isThirdStep={this.props.isThirdStep}
paginationCallback={this.handlePageChange}
pdfData={this.state.pdfData}
desiredWidth={600}
selectedPage={this.props.savedPageNo}
/>
</div>
</div>
);
} else {
return (
<div>
<ReferenceMenu />
</div>
);
}
}
In my component's render, I try to render several components based on certain conditions.
So, basically, the TablePoisition always stays there, and the PDFViewer and ReferenceMenu renders conditionally.
However, what I see on both conditions is only the TablePosition component.
Is this not supposed to work?
As explained since you want to combine two components you should change your render logic. One component will be sit there always and the other one will be rendered conditionally. So, you need to render that last component with the sticky one in the same return. I would do something like this:
renderPDFViewer = () => (
<div>
<div style={sideBySide}>
<PDFViewer
isThirdStep={this.props.isThirdStep}
paginationCallback={this.handlePageChange}
pdfData={this.state.pdfData}
desiredWidth={600}
selectedPage={this.props.savedPageNo}
/>
</div>
</div>
);
render() {
const tableStyle = this.getTableStyle();
const tableSettings = this.getTableSettings();
return (
<div>
<div style={tables}>
<TablePosition
contextMenuOn={true}
step={this.props.step}
pdfData={this.props.pdfData}
tableSettings={tableSettings}
tableStyle={tableStyle}
fileName={this.state.fileName}
tableSize={this.getTableSize()}
tableOffset={this.state.tableOffset}
desiredWidth={700}
updateXOffset={x => this.updateXOffset(x)}
updateYOffset={y => this.updateYOffset(y)}
markTable={() => this.markTable()}
setOutputLabels={(row, col, val) => this.setOuputLabels(row, col, val)}
/>
</div>
{
!this.props.isThirdStep
? this.renderPDFViewer()
: ( <div><ReferenceMenu /></div> )
}
</div>
);
}
You need to place your conditional renders inside variables or something similar.
var conditionContent1 = null;
var conditionContent2 = null;
if(condition1){
conditionContent1 = <div>conditional content 1</div>;
}
if(condition2){
conditionContent2 = <div>conditional content 2</div>;
}
return (
<div id="wrapper">
<div>
content
</div>
{conditionContent1}
{conditionContent2}
</div>
);
I added a wrapper div; because, I believe render's return doesn't like having multiple root elements.
If the variables are null; then, it won't affect the overall render.

How to remove a button if there is no more info in the api

The following code is running smoothly, but I want to implement it in a way that when I do a getNextPers() and there is no info, it hides/removes the Ver Mais button. I've been looking for solutions but have found none, so any help is good. Thank you.
import React from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
class List extends React.Component {
constructor(props){
super(props);
this.state = {
personagens: [],
page: 1,
showBtn: true,
};
this.getNextPers = this.getNextPers.bind(this);
}
getNextPers(){
const peopleApiEndpoint = `https://swapi.co/api/people/${this.state.page}`;
axios.get(peopleApiEndpoint).then((p) =>
if(p=={}){
this.setState({ showBtn: false });
}
else {
this.setState({ personagens: this.state.personagens.concat(p), page: this.state.page+1 })
}
);
}
render(){
return (
<div>
<p><b>Personagens:</b></p>
{this.state.personagens.map((pers, i) => (
<div key={i}>
<br />
<p><i>Name:</i> {pers.data.name}</p>
<p><i>Height:</i> {pers.data.height} cm</p>
<p><i>Mass:</i> {pers.data.mass} kg</p>
</div>
))}
<button onClick={this.getNextPers}>Ver Mais</button>
</div>
);
}
}
ReactDOM.render(<List />, document.getElementById('root'));
The real problem is here:
axios.get(peopleApiEndpoint).then((p) => {
if (p == {}) { // THIS WILL NEWER WORK AS EXPECTED
this.setState({showBtn: false});
} else {
this.setState({
personagens: this.state.personagens.concat(p),
page: this.state.page + 1
});
}
});
Also swapi return 404 when there is no more results instead of empty object so you need to add catch block to your axios.get as described in docs: https://github.com/axios/axios#handling-errors
axios.get(peopleApiEndpoint).then((p) => {
this.setState({
personagens: this.state.personagens.concat(p),
page: this.state.page + 1
});
}).catch((err) => {
this.setState({showBtn: false});
});
Now you can use conditional rendering like:
{(this.state.showBtn && <button onClick={this.getNextPers}>Ver Mais</button>)}
First thing getNextPers does not return anything and you can achieve the show/hide by using condintion in your code
{ this.your_condition ?
<button onClick={this.getNextPers}>Ver Mais</button> : ''
}
As addition to Ramya answer you can also use
render(){
return (
<div>
<p><b>Personagens:</b></p>
{this.state.personagens.map((pers, i) => (
<div key={i}>
<br />
<p><i>Name:</i> {pers.data.name}</p>
<p><i>Height:</i> {pers.data.height} cm</p>
<p><i>Mass:</i> {pers.data.mass} kg</p>
</div>
))}
{ this.state.showBtn && <button onClick={this.getNextPers}>Ver Mais</button> }
</div>
);
}
Since you're storing the showBtn state in your component, you can use it to conditionally render the button as follows:
render(){
return (
<div>
<p><b>Personagens:</b></p>
{this.state.personagens.map((pers, i) => (
<div key={i}>
<br />
<p><i>Name:</i> {pers.data.name}</p>
<p><i>Height:</i> {pers.data.height} cm</p>
<p><i>Mass:</i> {pers.data.mass} kg</p>
</div>
))}
{ (this.state.showBtn) ?
<button onClick={this.getNextPers}>Ver Mais</button>
:
null
}
</div>
);
}

react expand and collapse just one panel

Need help with react...
Trying to implement a collapsible list of cards with weather information.
Already implemented the behavior of expand and collapse, but when i clicked on one panel the other panel open at the same time (i have 2 panels and need 7 to display weahter for 7 days of the week).
How can i open and close just one panel?
Code:
import React, { Component } from 'react';
import Moment from 'react-moment';
import RandomGif from './RandomGif.js';
const urlForCity = city => `https://cors-anywhere.herokuapp.com/http://api.openweathermap.org/data/2.5/forecast/daily?q=${city}&units=metric&cnt=7&appid=1fba7c3eaa869008374898c6a606fe3e`
class OpenWapi extends Component {
constructor(props) {
super(props);
this.state = {
requestFailed: false,
shown: false
}
this.componentDidMount = this.componentDidMount.bind(this);
this.toggle = this.toggle.bind(this);
}
componentDidMount() {
fetch(urlForCity(this.props.city))
.then(response => {
if(!response.ok) {
throw Error("Network request failed")
}
return response;
})
.then(data => data.json())
.then(data => {
this.setState({
weatherData: data
})
}, () => {
this.setState({
requestFailed: true
})
})
}
toggle() {
this.setState({
shown: !this.state.shown
});
}
render() {
if(this.state.requestFailed) return <p>Request Failed.</p>;
if(!this.state.weatherData) return <p>Loading...</p>;
return (
<div>
<p>City: {this.state.weatherData.city.name}</p>
{/* Day 1 */}
<div onClick={this.toggle} className="dayWeekItem">
<div className="top-content">
<div className="icon-weather"></div>
<div className="date">
<div className="weekday">Today</div>
<div className="day-long"><Moment unix format="MMM DD YYYY">{this.state.weatherData.list[0].dt}</Moment></div>
</div>
<div className="temperature">
<div className="temp-high">{parseInt(this.state.weatherData.list[0].temp.max)}º</div>
<div className="temp-low">{parseInt(this.state.weatherData.list[0].temp.min)}º</div>
</div>
</div>
<div className={this.state.shown ? "toggleContent-open" : "toggleContent-closed"} >
<div className="weather-gif" >
<RandomGif keyword={this.state.weatherData.list[0].weather[0].description} />
</div>
</div>
</div>
{/* Day 2 */}
<div onClick={this.toggle} className="dayWeekItem">
<div className="top-content">
<div className="icon-weather"></div>
<div className="date">
<div className="weekday">Tomorrow</div>
<div className="day-long"><Moment unix format="MMM DD YYYY">{this.state.weatherData.list[1].dt}</Moment></div>
</div>
<div className="temperature">
<div className="temp-high">{parseInt(this.state.weatherData.list[1].temp.max)}º</div>
<div className="temp-low">{parseInt(this.state.weatherData.list[1].temp.min)}º</div>
</div>
</div>
<div className={this.state.shown ? "toggleContent-open" : "toggleContent-closed"} >
<div className="weather-gif" >
<RandomGif keyword={this.state.weatherData.list[1].weather[0].description} />
</div>
</div>
</div>
{/* Day 3 */}
{/* Day 4 */}
{/* Day 5 */}
</div>
)
}
}
export default OpenWapi;
I would have an object to represent the state, a field for each panel.
Like this:
constructor(props) {
...
this.state = {
requestFailed: false,
shown: {}
}
...
}
...
toggle(panelNumber) {
this.setState({
shown: {
...this.state.shown,
[panelNumber]: !this.state.shown[panelNumber]
}
});
}
...
The toogle function is used like this, for instance, Day 1:
<div onClick={() => this.toggle(1)} className="dayWeekItem">
...
</div>
And to show in html, for instance, Day 1:
<div className={this.state.shown[1] ? "toggleContent-open" : "toggleContent-closed"} >
<div className="weather-gif" >
<RandomGif keyword={this.state.weatherData.list[0].weather[0].description} />
</div>
</div>
They all will collapse always with your implementation.
You have a state
state = {
shown: true
}
You have a function to toggle it
toggle = () => {
this.setState(shown: !this.state.shown)
}
And you render the component, using the this.state.shown in two places, but the value will always be one true or false
render() {
return(<div .....//something>
<div onClick={this.toggle}>
{ this.state.shown ? <SomeComponent or HTML Tag> : null }
</div>
<div onClick={this.toggle}>
{ this.state.shown ? <SomeComponent or HTML Tag> : null }
</div>
</div>)
}
So where ever you toggle, once the state is updated and render method is called again to paint the view, both sections of divs get the sameBoolean` value. Therefore, they both collapse.
Best Solution I can offer for this problem will be:
Create a separate component which has two jobs to be do:
1. Maintains its own state, of collapse true or false.
2. Render the children given to it without wondering what they might be.
So let say
class WeatherWidget extends React.PureComponent {
state= {
shown: true
}
toggle = () => this.setState({shown: !this.state.shown})
render() {
return(
<div onClick={this.toggle} className="dayWeekItem">
<div className="top-content">
<div className="icon-weather"></div>
<div className="date">
<div className="weekday">Today</div>
<div className="day-long">
<Moment unix format="MMM DD YYYY">{this.props.date}</Moment>
</div>
</div>
<div className="temperature">
<div className="temp-high">{parseInt(this.props.maxTemp)}º
</div>
<div className="temp-low">{parseInt(this.props.minTemp)}º
</div>
</div>
</div>
<div className={this.state.shown ? "toggleContent-open" : "toggleContent-closed"} >
<div className="weather-gif" >
<RandomGif keyword={this.props.gifDescription} />
</div>
</div>
</div>
)
}
}
So you create a reusable component which manages its own state ( React Paradigm/ Composition brings reusability)
As for displaying multiple widgets
class OpenWapi extends Component {
constructor(props) {
super(props);
this.state = {
requestFailed: false,
shown: false
}
this.componentDidMount = this.componentDidMount.bind(this);
this.toggle = this.toggle.bind(this);
}
componentDidMount() {
fetch(urlForCity(this.props.city))
.then(response => {
if(!response.ok) {
throw Error("Network request failed")
}
return response;
})
.then(data => data.json())
.then(data => {
this.setState({
weatherData: data
})
}, () => {
this.setState({
requestFailed: true
})
})
}
render() {
if(this.state.requestFailed) return <p>Request Failed.</p>;
if(!this.state.weatherData) return <p>Loading...</p>;
return(
<div>
<p>City: {this.state.weatherData.city.name}</p>
<WeatherWidget
date={this.state.weatherData.list[0].dt}
maxTemp={this.state.weatherData.list[0].temp.max}
minTemp={this.state.weatherData.list[0].temp.min}
gifDescription=
{this.state.weatherData.list[0].weather[1].description}
/>
<WeatherWidget
date={this.state.weatherData.list[1].dt}
maxTemp={this.state.weatherData.list[1].temp.max}
minTemp={this.state.weatherData.list[1].temp.min}
gifDescription=
{this.state.weatherData.list[1].weather[1].description}
/>
</div>
)
}
Hopefully, this solves the use case.

Categories

Resources