react if data present else something else in component - reactjs

I have a react component that is like :
class List extends Component {
render() {
const {infos} = this.props
var info;
if(infos.user_info ){
info = infos.user_info.filter(inf => inf.id).map((inf =>{
return <div className={"inf"} style={{height:"300px", width:"300px"}} key={inf.id} >
<p>{ inf.name }</p>
<img src={inf.thumbnail} height="250px" width="250px" />
</div>
}))
}
return (
<div> {info} </div>
)
}
}
export default List
Here I have problem with image part. I want to display the information of user with image. Here not all the user info might have images. Some have null value too.
<img src={inf.thumbnail} height="250px" width="250px" /> Here I want to display the thumbnail if it is available else I want to display some random picture..
I hope you guys understand.. How can I do this ??
Thank you

You can use the conditional operator.
inf.thumbnail ?
<img src={inf.thumbnail} height="250px" width="250px" /> :
<img src="something-else.png" />
This will only show the thumbnail if inf.thumbnail is not undefined, null, false or ''.

Related

How to solve react hydration error in Nextjs

I have created small nextjs page using wordpress REST API, Now react-hydration-error error show this page.I am using react html parser npm. How do I solve this error. could you please solve this error.
my code:
import Image from 'next/image'
import React ,{Component}from 'react'
import Link from 'next/link';
import { BiCalendar } from "react-icons/bi";
import ReactHtmlParser from 'react-html-parser';
export default class Blog extends Component{
constructor(props){
super(props);
this.state={
data: props.bloglist,
isLoading: true,
dataLoaded: false,
};
}
render(){
if (!this.state.data) {
return null;
}
console.log(this.state.data)
return(
<>
<div className="container blog-section">
<div className='row'>
<h2>Latest Posts</h2>
</div>
<div className='row'>
{
this.state.data.map(((x,i) =>(
<div className='col-md-4 boxs text-center' key={i}>
<div className='bg-info'>
<img src={x.images.large} className='img-fluid'/>
<h3>{x.title.rendered} </h3>
<p className='shopping'><span><BiCalendar/> {x.date}</span> </p>
{/* <p dangerouslySetInnerHTML={{__html: x.excerpt.rendered}}></p><span><BiShoppingBag/> {x.slug}</span> */}
<p class='expert'>{ReactHtmlParser(x.excerpt.rendered)}</p>
<Link href={"/blog"+"/"+x.slug+"/"+x.id } passHref={true}><p className='readmore'><span>Readmore </span></p></Link>
</div>
</div>
)))
}
</div>
</div>
</>
)
}
}
My original issues:
paragraph coming this format <p>If you have heard that there are ways to make money while shopping in the UAE and would lik</p> from API, So I converted to html.
I had this error, in my case I had <p> tag nested inside another <p> tag,
I was using Typography (MUI v5) to render text, switching to <Box> from <Typography> fixed the error.
We use components to build the React-based websites, These components are made using HTML tags. It is very important not to nest the same HTML elements.
For Example:
function Logo() {
return (
<Link href="/">
<a>
<Image
src="/images/logo.svg"
width={100}
height={75}
/>
</a>
</Link>
);
}
export default Logo;
Above is the Logo Component which has already the <a></a> tag inside it.
In this example, you will get the React Hydration Error if the <a> tag is used inside another <a> tag.
<a href="#">
<Logo />
</a>
So do not include the same HTML tags, which are hidden inside the
components to avoid react hydration error.
In my case I am using NextJS and I had a dropdown with react-select, the default value was changing after a small calculation, that does not like to nextjs, this is my previous code:
<Select options={seasons}
onChange={() => setSeason(e.value)}
defaultValue={seasons.find((x) => x.value == season) ? seasons.find((x) => x.value == season) : seasons[0]}
/>
So, I changed that calculation to the useEffect and initialized the react-select dropdown only when that value was calculated,now this is my current code that works:
{defaultSeason && (<Select options={seasons}
onChange={() => setSeason(e.value)}
defaultValue={defaultSeason}
/>)}
So, basically check that the defaultValue or anything else does not change after the html is sent to the client part in NextJS.
Follow these: https://nextjs.org/docs/messages/react-hydration-error
Or try deleting <a> within <Link> maybe.
My first code was this:
const isUserLoggedIn = is_user_logged_in()
// is_user_logged_in() checks for cookie of user token and returns boolean
Got the error about hydration
Then changed code to this:
const [isUserLoggedIn, setIsUserLoggedIn] = useState(null)
useEffect(() => {
setIsUserLoggedIn(is_user_logged_in())
}, [])
Renders was like this:
{isUserLoggedIn ? (
<>
{/* After login */}
<Profile USER={USER}/>
</>
) : (
<>
{/* Before login */}
<SigninButtons/>
</>
)}
And error solved
You can also check this
https://nextjs.org/docs/messages/react-hydration-error
Just try restarting the server. npm run dev. It worked for me. I was using react-hot-toaster.
Also try to check if you have sth like this:
<p>
<div>
Hello
</div>
</p>
div cant be inside p tag

How to render my Modal window and all the information contained inside ( in React)?

My application renders twelve random people fetched from a different website. Everything works fine apart from my modal component(it should render more information about the person you clicked). For some reason whenever I try to render it I get this error 'Modal.js:9 Uncaught TypeError: Cannot read property 'medium' of undefined' and more errors comes with it. I am printing props.modalInfo from the Modal component to the console and it does have all the information I need, but for some reasons it shows that props.modalInfo is undefined when I try to render it. I have never done modal box in React (I am a beginner). Could someone explain me how I can render my Modal and pass all the data successfully? Thank you in advance!
handleClick(id) {
this.setState((prevState) => {
const modalInfoToPass = prevState.employeeList.filter(employee =>
{
if(`${employee.name.first} ${employee.name.last}` === id){
// get only and only one object that fulfils the
// condition
return employee;
}
})
return {
displayModal: true,
// update the modalInfo state
modalInfo: modalInfoToPass
}
})
}
render(){
return (
<div className='container'>
<Header />
<main>
{
this.state.loading ? <h2 className='load-page'>Loading...</h2> :
this.state.employeeList.map(employee =>
<Employee key={`${employee.name.title}
${employee.name.last}`}
employeeInfo={employee}
**handleClick={this.handleClick}**
/>)
}
</main>
<Footer />
**{this.state.displayModal && <Modal modalInfo={this.state.modalInfo} />}**
</div>
);
}
function Modal(props) {
**console.log(props.modalInfo);**
return (
<div className='bg-modal'>
<div className='modal-content'>
<div className='modal-image'>
<img src={props.modalInfo.picture.medium} alt={`${props.modalInfo.name.title} ${props.modalInfo.name.first}`}/>
</div>
<div className='modal-info'>
<p className='name'>{props.modalInfo.name.first} {props.modalInfo.name.last}</p>
<p className='email'>{props.modalInfo.email}</p>
<p className='place'>{props.modalInfo.location.city}</p>
</div>
<hr />
<div className='modal-more-info'>
<p className='number'>{props.modalInfo.cell}</p>
<p className='address'>{`${props.modalInfo.location.street}, ${props.modalInfo.location.state}`}</p>
<p className='postcode'>{props.modalInfo.location.postcode}</p>
<p className='birthday'>{props.modalInfo.dob.date}</p>
</div>
</div>
</div>
);
}
What is id and is it on an employee? If it isn't available, you could just pass what you're filtering for in your handleClick:
handleClick={()=>this.handleClick(`${employee.name.first} ${employee.name.last}`)}
Or, you could just pass the employee:
handleClick={()=>this.handleClick(employee)}
and modify your handler:
handleClick(employee) {
this.setState({modalInfo: employee, displayModal: true})
}

How to check if profile images exist else use fallback jpg in a react App

I am displaying search results in a React App. The file img src={/users/${id}/avatar.jpg} does not exist for all users. The user's gender is available in the field $gender. If they do not have an avatar.jog uploaded, I want to use male.jpg for gender=male and female.jpg for gender=female.
Below is the component code:
import React, { Component } from 'react'
import AppLink from '../../others/link/link'
class SearchResult extends Component {
</span>
</div>
<div className="mb1">
<span><span className="text-bold">Gender: src here</span>
</div>
</div>
</div>
</div>
)
}
}
export default SearchResult
The logic for determining a user's profile images might be better placed in your backend, so that your overall design for fetching and displaying avatar images is simpler an more robust.
If a user has not uploaded an avatar image, the server can decied what image to serve for that user by the user's id (ie to serve an avatar if one has been uploaded, or serve a gender image as a fallback). That saves potential issues in your front end code (ie valid client side user data, but no avatar image on server, causing image not found error).
If however, you know that an avatar exists when say, the users id is defined, then the following might might your requirements:
class SearchResult extends Component {
render() {
let {
id,
username,
firstname,
surname,
gender
} = this.props
// Determine the avatarImage path depending on the existance of a valid
// user id. If user id is invalid, fallback to an image based on gender
const avatarImage = (id !== undefined && id !== null) ?
`/users/${id}/avatar.jpg` : `/${ gender }.jpg`
return (
<div className="user_item">
<div className="user-container">
<div className="user-l">
<div className="text-center">
<AppLink url={`/profile/${username}`}>
{/* Apply the computed avatarImage to the img element /*}
<img src={ avatarImage } className="user_avatar" />
</AppLink>
</div>
</div>
<div className="user-m half-container">
<div className="halfL">
<div className="mb1">
<AppLink
url={`/profile/${username}`}
className="lead m2 s_userName"
label={username}
/>
</div>
<span>{firstname} {surname}</span>
</div>
<div className="halfR">
<div className="mb1">
<span>
<span className="text-bold">Age:</span> {age}
</span>
</div>
<div className="mb1">
<span><span className="text-bold">Gender:</span> {gender}</span>
</div>
</div>
</div>
<div className="mb1">
<AppLink
url={`/profile/${username}`}
className="btn btn-sm"
label={`Contact ${username}`}
/>
</div>
</div>
</div>
</div>
)
}
}
export default SearchResult
This answer is not an ideal solution (as identified above, you should be storing the user's avatar state in your database), however it shows a strategy to resolve the user avatar from the client in order to achieve what you're after.
In short, this approach will issue a request to your back-end to see if the user's avatar image exists on the server. If the request is successful, that avatar image url is stored in the component and used for subsequent rendering.
If the request fails, the component applies the "fallback" behaviour - that is, it will use the input props to deduce the "gender" image, similar to that shown above.
See [UPDATED] tags below for relevant additions from your current code:
class SearchResult extends Component {
constructor(props) {
super(props)
/* [UPDATED] Setup the default userImage to be initially displayed */
this.state = {
userImage : `/images/users.jpg`
}
}
/* [UPDATED] When the component is mounted, use the id and gender props
to decide which image to display for the user
*/
componentDidMount() {
const { id, gender } = this.props
const avatarImage = `/users/${id}/avatar.jpg`
/* [UPDATED] Query the server for the user's avatar - if the query
succeeds then use the avatar image, otherwise fallback to gender
image. In either case, the userImage is stored in the components
state
*/
fetch(avatarImage).then(response => {
if(!response.ok) {
this.setState({ userImage : `/${ gender }.jpg` })
}
else {
this.setState({ userImage : `/users/${id}/avatar.jpg` })
}
})
}
render() {
let {
id,
username,
firstname,
surname,
gender
} = this.props
{/* [UPDATED] Extract userImage from state /*}
const { userImage } = this.state
return (
<div className="user_item">
<div className="user-container">
<div className="user-l">
<div className="text-center">
<AppLink url={`/profile/${username}`}>
{/* [UPDATED] Apply the userImage to the img element based on state /*}
<img src={ userImage } className="user_avatar" />
</AppLink>
</div>
</div>
<div className="user-m half-container">
<div className="halfL">
<div className="mb1">
<AppLink
url={`/profile/${username}`}
className="lead m2 s_userName"
label={username}
/>
</div>
<span>{firstname} {surname}</span>
</div>
<div className="halfR">
<div className="mb1">
<span>
<span className="text-bold">Age:</span> {age}
</span>
</div>
<div className="mb1">
<span><span className="text-bold">Gender:</span> {gender}</span>
</div>
</div>
</div>
<div className="mb1">
<AppLink
url={`/profile/${username}`}
className="btn btn-sm"
label={`Contact ${username}`}
/>
</div>
</div>
</div>
</div>
)
}
}
export default SearchResult
Hope this helps!

How to have backup URL show if the JSON data is undefined?

const SearchResults = ({ artists }) => (
<div className="search-results">
{artists.map(val => (
<a href="# " key={uniqid()}>
<h3>{val.name}</h3>
<img
className="box-img"
src={
val.images[0].url
? val.images[0].url
: 'https://www.w3schools.com/w3css/w3css_images.asp'
}
alt=""
/>
</a>
))}
</div>
);
I have an API call going to Spotify to get a list of Artist. When the results all have an image there is no problem but if they don't, React just returns undefined and I can't figure out how to have the placeholder image show.
You can simply have a bare png default image for this in your project, then import it and use it when no image is returned from spotify, something like:
import defaultArtistImage from './myProject/assets/images/defaultArtistImage.png';
...
const SearchResults = ({ artists }) => (
<div className="search-results">
{artists.map(val => (
<a href="# " key={uniqid()}>
<h3>{val.name}</h3>
<img
className="box-img"
src={
val.images.length !== 0
? val.images[0].url
: defaultArtistImage
}
alt=""
/>
</a>
))}
</div>
);
this is simpler than retrieving the image from an external server. Also, doing val.images[0].url can give you an error if .images it's an empty array

React component with Edit Mode and View Mode, is this a correct pattern?

I have a react component which displays a recipe. This component can be used to just view the data and also to edit the data, depending on a 'edit' prop being passed it.
At the moment I have some conditional logic which will hide/show certain elements depending on whether the user wants to edit or view the recipe. Here is my render function:
render() {
let buttons = null;
if (this.props.edit === 'true') {
buttons = <div className="buttonList">
<button onClick={this.onSave} className='defaultBtn'>Save</button>
<button onClick={this.goBack} className='defaultBtn'>Discard Changes</button>
</div>;
} else {
buttons = <div className="buttonList">
<button onClick={this.goBack} className='defaultBtn'>Back</button>
</div>;
}
return (
<div className="single">
<img src={this.state.recipe.imageURL} />
<div className='recipeDetails'>
<h1>{this.state.recipe.name}</h1>
{this.props.edit === 'true' > 0 &&
<TextField type='text' floatingLabelText='Image URL' onChange={this.onImageUrlChange}></TextField>
}
<IngredientList onIngredientChange={this.onIngredientChange}
onDelete={this.onDelete}
ingredients={this.state.recipe.ingredients}
edit={this.props.edit}
addIngredient={this.addIngredient} />
{buttons}
</div>
</div>
);
}
Is this the best way to achieve this? Using if statements like this feels wrong to me. I feel like I should have a ViewRecipe component and a EditRecipe component that share most of the code but have some logic to hide and show the relevant elements. Is there a certain React Pattern to do this? I've read a little about High Order Components but not sure if they fit this particular problem.
Am I overcomplicating this?
Should I just have two separate components?
Most of the logic on the Edit side of things.
Your props naming needs review :
props.edit ='true' 🤔 it can be props.mode = 'edit' or 'view'
mitigate the conditional logic (if...else) of render method and break down it into methods prefixed by "render".
Solution will be :
renderButtons() {
if (this.props.mode === 'edit')
return (
<div className="buttonList">
<button onClick={this.onSave} className='defaultBtn'>Save</button>
<button onClick={this.goBack} className='defaultBtn'>Discard Changes</button>
</div>
)
else {
return (
<div className="buttonList">
<button onClick={this.goBack} className='defaultBtn'>Back</button>
</div>
)
}
}
renderTextField() {
if (this.props.mode != 'edit') return null;
return (
<TextField type='text' floatingLabelText='Image URL' onChange={this.onImageUrlChange}></TextField>
)
}
render() {
return (
<div className="single">
<img src={this.state.recipe.imageURL} />
<div className='recipeDetails'>
<h1>{this.state.recipe.name}</h1>
{this.renderTextField()}
<IngredientList onIngredientChange={this.onIngredientChange}
onDelete={this.onDelete}
ingredients={this.state.recipe.ingredients}
edit={this.props.edit}
addIngredient={this.addIngredient} />
{this.renderButtons()}
</div>
</div>
);
}

Resources