How to conditionally render a prop initialized as an empty object? - reactjs

My application has a user input a query to make a request to the Pokemon API and the response is rendered. Prior to the user making a request, it shows No Pokemon yet, please submit a Pokemon.
I initialized pokemonCharacter as an empty object being passed to the PokemonInfo component. However, my conditional render logic is not working.
Please let me know how to solve this. https://codesandbox.io/s/pokedex-5j1jf
The following are my failed attempts.
Attempt #1
let myDiv;
if (pokemonCharacter && pokemonCharacter.length > 0) {
myDiv = <div>
<p>{pokemonCharacter.name}</p>
<img src={pokemonCharacter.sprites.front_default} alt="pokemon" />
</div>
} else {
myDiv = <p>No Pokemon yet, please submit a Pokemon!</p>
}
return ({myDiv})
Attempt #2
{(pokemonCharacter && pokemonCharacter.length > 0) ?
<div>
<p>{pokemonCharacter.name}</p>
<img src={pokemonCharacter.sprites.front_default} alt="pokemon" />
</div>
: <p>No Pokemon yet, please submit a Pokemon!</p>}
Attempt #3
const list = pokemonCharacter => {
if (!pokemonCharacter) {
return null;
}
if (!pokemonCharacter.length) {
return <p>No Pokemon yet, please submit a Pokemon!</p>
} else {
return (
<div>
<p>{pokemonCharacter.name}</p>
<img src={pokemonCharacter.sprites.front_default} alt="pokemon" />
</div>
)
}
}
return (
{list}
);

Where you are checking the loading status, just check if the status is false or not then display the component.
{ loading
? <p>Loading...</p>
: <PokemonInfo pokemonCharacter={pokemonCharacter} />
}

I solved this by checking if pokemonCharacter.name is truthy in the PokemonInfo component, as opposed to just checking if pokemonCharacter the object as a whole is truthy.
{pokemonCharacter.name ?
<div>
<p>{pokemonCharacter.name}</p>
<img src={pokemonCharacter.sprites.front_default} alt="pokemon" />
</div>
: <p>No Pokemon yet, please submit a Pokemon!</p>}

Related

GET data:image/jpg;base64, false net::ERR_INVALID_URL

I am getting an error while I am trying to use base64 images I have fetched from backend. All the backend APIs are working properly. I am getting all the base64 images as response also, but images are not appearing and I am getting this error too. Can anyone fix this? Thank you in advance. :)
useEffect hook:
useEffect(()=>{
const config={
headers:{
"Content-Type":"application/json",
Authorization:`Bearer ${localStorage.getItem("token")}`
}
}
axios.get(`/api/user/public/getalbums/${id}`,config ).then(({data})=>{
setAlbum(data);
const arr=[];
for(let i=0;i<data.length;i++){
axios.get(`/api/user/private/readimage/${data[i].fileUrl}`,config).then((res)=>{
console.log(res.data);
console.log("res");
arr.push(res.data);
// setPhotos([...photos,res.data])
})
}
console.log(arr);
setPhotos(arr);
// setPhotos([...photos,res.data])
}
)
},[])
Image:
{album.length>0 && album.map((data,ind)=>{
return(
<div key={ind}>
<div className='album-card-1' ><img className="album-card-img" src={`data:image/jpg;base64, ${photos.length>0 && photos[ind]}`} onClick={()=>{
navigate(`/artist/${id}/user/album/${data._id}`)
}}/></div>
</div>
)
}
)}
Error:
data:image/jpg;base64, false
net::ERR_INVALID_URL
Your HTML code is correct, it should be showing the correct image if the base64 is coming correctly.
Probably your error is on your logic related to the album and photos arrays.
Please add an example of the values of these arrays (The console.log that you're printing).
Also, you can add a validation that check if the base 64 is not false before rendering your JSX:
return album.length > 0 && album.map((data, ind) => {
return photos.length > 0 && photos[ind] && (
<div key={ind}>
<div className='album-card-1'>
<img className="album-card-img" src={`data:image/jpg;base64, ${photos[ind]}`} onClick={() => navigate(`/artist/${id}/user/album/${data._id}`)}/>
</div>
</div>
)
});

map is not a function on array React

I'm getting an error that map is not a function on my data.
I'm getting a response back from an api that is returning an array of objects. When I don't refresh the page I can view the results displayed just fine and even navigate to view them individually (when I click on see more). However, when I refresh the page I get the
error of "Map is not a function" on my props even though the results are displaying in the console log.
I'm lost here and can't figure out why it's doing that.
componentDidMount() {
this.props.getCanyons();
}
render() {
const { canyons } = this.props;
console.log(canyons)
return (
<section>
{canyons.map(canyon => (
<section key={canyon.canyon_id}>
<h3>{canyon.canyon_name}</h3>
<img src={canyon.canyon_pic} alt={canyon.canyon_name} />
<Link key={canyon.canyon_id} to={`/canyon/${canyon.canyon_id}`}>
<button>See More</button>
</Link>
</section>
))}
</section>
);
}
}
When the api failed or having lag time to get response, it may be undefined. This kind of checking prevent you to from such problem.
return (
{canyons && canyons.map(canyon => (
...skipped code
))}
)
Typescript provide feature of adding a ? before try to access the related Object type variable
//In typescript
{canyons?.map(canyon => (
...skipped code
))}
componentDidMount() {
this.props.getCanyons();
}
render() {
const { canyons } = this.props;
console.log(canyons)
return (
<section>
{ canyons !== '' || canyons.length > 0 ? //change here
canyons.map(canyon => (
<section key={canyon.canyon_id}>
<h3>{canyon.canyon_name}</h3>
<img src={canyon.canyon_pic} alt={canyon.canyon_name} />
<Link key={canyon.canyon_id} to={`/canyon/${canyon.canyon_id}`}>
<button>See More</button>
</Link>
</section>
))
:
null
}
</section>
);
}
}
Please follow the change. It should works for you...
Many browsers provide a live view when using console.log(). When the request not finished 'canyons' is undefined. Use
console.log(JSON.parse(JSON.stringify(obj)))
For this problem, try to set default value or check variable first

React - onClick event not working correctly

I'm attempting to pass an onClick function as a prop to a child component in React. However, nothing is being logged to the console when the button is clicked. For now I'm just trying to console log to make sure the event is actually firing.
Any Ideas?
class App extends React.Component {
togglePallets = (pallet) => {
console.log('test');
}
render() {
return (
<div className="mainWrapper">
<div className="mainContainer">
<div>
<img src="images/picture-of-me.jpg" alt="Me"></img>
</div>
</div>
<SideBar toggle={this.togglePallets} showPallets={[this.state.showAboutPallet, this.state.showLanguagesPallet,
this.state.showProjectsPallet, this.state.showContactPallet]}/>
{this.state.showAboutPallet && <AboutPallet />}
{this.state.showAboutPallet && <LanguagesPallet />}
{this.state.showAboutPallet && <ProjectsPallet />}
{this.state.showAboutPallet && <ContactPallet />}
</div>
);
}
}
function SideBar(props) {
return (
<div className="sideBarContainer">
<Button icon={faUser} showAboutPallet={props.showPallets[0]} onClick={props.toggle}/>
</div>
);
}
What you have written is correct. But we can try it in another way using an arrow function.
onClick={(e) => props.toggle(e,data)}
And, make relevant changes in toggle function, so it may support multiple arguments.
Change your togglePallets to any of the below
togglePallets() {
console.log("test");
};
If you want to access event then
togglePallets(event) {
console.log("test");
};
Or
togglePallets=event =>{
console.log("teeventst");
};

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})
}

react if data present else something else in component

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 ''.

Resources