React If / else for picture src - reactjs

I want the image src for to change based on the value of the "p" element. I have imported all of my images like this:
import food from '../../images/food.png'
I've tried to use if/else statements and wrapping them in a function, then mounting them with componentDidMount when the page loads up, but that doesn't work for me. Then I tried :
images = () => {
const image = document.querySelectorAll('img');
let src = image.attr('src');
if (src.valueOf() === 'Food') image.src = {food};
// Changed src.val() because that didn't work //
}
componentDidMount() {
this.images()
)}
And this does nothing for me either. Any suggestions?
MAIN BODY OF CODE:
(top of code not show)
return (
<GuideDiv>
<div className='top'>
<h1>Guides</h1>
<NewGuide to='/GuideForm'>
<h2> Add <img src={travel} alt='ravel'/> Guide </h2>
</NewGuide>
</div>
{guided.map(guide =>
<GuidePost key={guide.id}>
<div>
<UserIcon>
<img id='guide' alt='type' src={guide.guide_type}/>
</UserIcon>
<label className='under'>Guide Type</label>
<br/>
<p>{guide.guide_type}</p>
<br/>
(rest of code not shown)

Why don't you try an mapping. Something like this if its predefined set
import food from '../../images/food.png'
import car from '../../images/car.png'
let mapping = {
FOOD: food,
CAR: car
}
const images = () => {
const image = document.querySelectorAll('img');
let srcVal = image.attr('src')?.valueOf;
image.src = mapping[srcVal];
//....rest of your code
}
Check this one and let me know whether it helped you

THANK YOU!!!
With a little modification, I did the suggested object map and then:
let imgURL = {
Food: food,
Stay: stay,
Sites: sites,
Tips: tips
}
<img id='guide' alt='user' src={imgURL[guide.guide_type]}/>

Related

Flickity cell selector in React

Basically I have a dropdown in which each option has an attribute corresponding to the ID of an image. My goal is to go to that image when an option is chosen. For that I am trying to use:
const myCustomNext = () => {
flkty.selectCell(somevar)
};
somevar is initially set to #someid, when I click my button, it goes to the cell with that ID perfectly.
The issue starts once I update the value of somevar. As soon as I do and then click the button, I get the following Error:
"Cannot read property 'selectCell' of null"
I logged both the initital somevar and the updated one. Other than the ID itself, they are absolutely identical so I have no clue where I am going wrong. I tried switchen the static and reloadOnUpdate settings but that didn't help.
Here a more complete example that might show better what I am trying to do:
const FlickTest = () => {
const [varimg, setVarimg] = useState("#cG9zdDoxNA");
let flkty = null;
function setVariant(e) {
let index = e.target.selectedIndex;
let optionElement = e.target.childNodes[index]
let option = optionElement.getAttribute('data-imgid');
setVarimg(`#${option}`);
}
const myCustomNext = () => {
flkty.selectCell(varimg)
};
return (
<>
<button onClick={myCustomNext}>My custom next button</button>
<select onChange={setVariant}>
{variants.map((variant) =>
<option data-imgid={variant.gallerie[0].id} value={variant.farbe} key={variant.farbe}>{variant.farbe}</option>
)}
</select>
<Flickity
flickityRef={c => (flkty = c)}
className={'carousel'}
elementType={'div'}
options={flickityOptions}
disableImagesLoaded={true}
reloadOnUpdate={true}
static={true}
>
{variants.map((galitem) =>
galitem.gallerie.map((galimg) =>
<div key={galimg.id} id={galimg.id.replace(/[^\w\s]/gi, '')}>
<span>{galimg.id}</span>
<Image fluid={galimg.localFile.childImageSharp.fluid} />
</div>
)
)}
</Flickity>
</>
)
}
Any ideas or pointers would be much appreciated :)
Switched from a dropdown to buttons just to simplify the whole thing and see where it goes wrong. Seems like flickity only accepts the value directly but not from state or any other variable.
This works:
const selectSlide = (e) => {
flkty.selectCell( `.${e.target.getAttribute("data-selector")}` )
};
...
<button onClick={selectSlide} data-selector={variant.gallerie[0].id} key={variant.farbe}>{variant.farbe}</button>
If anybody knows if this is a flickity thing or (more likely) I was doing something completely wrong I'd still appreciate some pointers so I know better next time :)

Image (<img) tag is not rendered when using ReactMarkdown in react js

Currently I am trying to fetch the github readme file and render it using ReactMarkdown. here is the screenshot of output/error.
there are some tag like
<p float="left"> <img src="https://github.com/username/project/blob/master/Screenshots/s1.png" width="300" hspace="40"/> </p>
So above tag does not render and gives CORB error.
My current code is
<ReactMarkdown
className="projectDetail__markdown"
escapeHtml={false}
transformImageUri={(uri) =>
uri.startsWith("https")
? uri
: `https://raw.githubusercontent.com/AlShevelev/WizardCamera/master/screenshots/5_2_small.webp`
}
source={markDown}
// astPlugins={[parseHtml]}
renderers={{ code: CodeBlock }}
</ReactMarkdown>
I have tried use plugin but no success.
Finally I founded the solution.
I saw CORB error in console I research about why this was happening and founded that in readme file url of images were not correct.
The readme url were https://github.com/username/project/blob/master/Screenshots/s1.png &&
required Url was: https://raw.githubusercontent.com/username/project/master/screenshots/s1.png
So the problem was that when we set the src for the image, we need to use a URL which points to an actual image and first url was not pointing to actual image.
this was the root cause and because of this images were not rendering.
So I write code to convert all the urls of img tags only of markdown response.
https://playcode.io/666242/ complete code.
// This function will find all the links in img tag.
function getImages(string) {
const imgRex = /<img.*?src="(.*?)"[^>]+>/g;
const images = [];
let img;
while ((img = imgRex.exec(string))) {
images.push(img[1]);
}
return images;
}
// This function convert the markdown text.
const convertImgInMarkdown = (markDown) => {
let mark = markDown;
let imageTags = getImages(mark);
let updatedImages = [];
imageTags.map((image) => {
let xx = image.split(".com");
let y = `https://raw.githubusercontent.com` + xx[1];
let z = y.replace("/blob", "");
updatedImages.push(z);
});
for (let i = 0; i < updatedImages.length; i++) {
mark = mark.replace(imageTags[i], updatedImages[i]);
}
return mark;
};

Buggy movement of Object in Array with Redux and React

Basically I'm trying to move a single object within an Array of object, but when I move the same object once or twice it starts moving the other object in said array.
So I have tried making a new Array with .slice() then .shift(item) by it's index and then add it back in at the right index with .splice(newIndex, 0, item), once the array has been update I push it to the Redux store which updates my Megadraft(ie Draft.js) application.
I have also tried directly manipulating the original array, ie this.props.array (like your meant too with Redux) and using the keys inside of the objects instead of the indexes.
import React from 'react';
import { MegadraftPlugin, DraftJS, CommonBlock } from "megadraft"
export default class ImageGalleryBlock extends React.Component {
_moveImgOneBack = (e, images, index) =>{
e.preventDefault()
let newPlace = index - 1
if(newPlace == -1){
newPlace = images.length
}
const image = images.shift(index)
images.splice(newPlace, 0, image)
return this.props.container.updateData({ images: images })
}
_moveImgOneForward = (e, images, index) =>{
e.preventDefault()
let newPlace = index +1
if(newPlace > images.length){
newPlace = 0
}
const image = images.shift(index)
images.splice(newPlace, 0, image)
return this.props.container.updateData({ images: images })
}
render(){
return (
<CommonBlock {...this.props} actions={this.actions} title="Image
Gallery">
<BlockContent>
<div className='gallery-cms-block'>
{ this.props.images.map((obj, index)=> {
return(
<div key={obj.key} className="image-box">
<button title="Move image back one" className="move-button"
onClick={(e)=> this._moveImgOneBack(e,
this.props.data.images, index)}>◀ {index}</button>
<img className="image" src={`${obj.image.uri}?
id=${obj.image.id}`} />
<div>
<button key={obj.key} title="Move image forward one"
className="move-button" onClick={(e)=>
this._moveImgOneForward(e, this.props.data.images,
index)}>▶</button>
</div>
</div>
)
}) }
</div>
</BlockContent>
</CommonBlockMKII>
);
}
}
I expect the the button(ether forward or backward) to move said item and only the said item.
The results are that it will move the item once... maybe twice then get suck moving all the other items in the array.
... your using shift wrong:
array = ['foo', 'bar', 'not', 'feeling', 'welcome', 'by jack', 'ass users']
array.shift(whatEverIndex)
the output will always be the first index, i.e 'foo', and
because your index is correct and your using
array.splice(newIndex, 0, item)
properly your array is changing in a strange fashion.
Try copying the desired item then delete it with .splice(), like this:
const item = array[index] //copy item
array.splice(index, 1) //remove old item
array.splice(newIndex, 0, item) //place item
funny that none of you guys NaN, laruiss, Antoine Grandchamp, J-Alex took the time to actually do what you should on stackoverflow... you know help someone out. damn vete a cascarla, Good luck Reece hope this solved it for you.
Thanks #Whitepaw,
I've updated my code with:
_moveOneImgBack = (newArray, index) =>{
const arrayLength = newArray.length - 1
const newBackPlace = index == 0 ? arrayLength : index - 1
const image = newArray[index]
newArray.splice(index, 1)
// const image = images.shift(index)
newArray.splice(newBackPlace, 0, image)
this.props.container.updateData({ images: newArray })
}
and it now works perfectly, I got stuck on the fact it might have something to do with redux immutables. So thats for pointing out the misuse of .shift()

ReactJS - embedding custom element in a custom element

I just started to learn ReactJS and encountered a problem that I can't solve.
I'm creating a basic application for TV Shows. I have a bootstrap tab for every season of a show and within this tab I want to list all the episodes of the selected season. The problem is that I have to create the tabs in a loop, and within this loop I should have another loop for the episodes.
I'm trying to do something like this:
EpisodeCards(props) {
return (
<div>
This should contain the details of the episodes
</div>
)
}
SeasonTabs(props) {
console.log('Seasons: ', props.seasons)
let tabs = [];
let episodes = [];
let currentSeason = 1;
let id;
let aria;
for(let season of props.seasons) {
episodes = [];
id="nav-season" + currentSeason;
aria = "nav-season" + currentSeason + "-tab";
tabs.push(<div className="tab-pane fade" id={id} role="tabpanel" aria-labelledby={aria}><this.EpisodeCards episodes={season}></this.EpisodeCards></div>);
currentSeason++;
}
return (
<div className="tab-content py-3 px-3 px-sm-0" id="nav-tabContent">
{tabs}
</div>
)
}
For this I am getting the following error:
Unhandled Rejection (TypeError): Cannot read property 'EpisodeCards' of undefined
How can this be done in the 'react way'? Thanks in advance.
Change
SeasonTabs(props)
to
SeasonTabs = (props) =>
You want to access a class property using this but by default its not binded to the function (ES5 only) by creating the functions using arrow () =>(new ES6 syntax) it automatically bind this to the function.
For Example:
class Test extends Component{
constructor(props){
this.testFn= this.testFn.bind(this);
}
testFn(){
console.log(this); //will output
}
testFn2(){
console.log(this); // undefined
}
testFn3 = () =>{
console.log(this); //will output
}
}
Reactjs is all about components, everything is component. If a function return a react element or Custom element then is a component.
You are creating a functional component inside of a class component, while this approach may work but this is not appropriate way to make component.
It is better to use composition, your code will be more clear, easier
to read, better maintainability and you can use component in other
components.
My solution:
function EpisodeCards(props) {
return (
<div>
This should contain the details of the episodes
</div>
)
}
SeasonTabs(props) {
console.log('Seasons: ', props.seasons)
let tabs = [];
let episodes = [];
let currentSeason = 1;
let id;
let aria;
for(let season of props.seasons) {
episodes = [];
id="nav-season" + currentSeason;
aria = "nav-season" + currentSeason + "-tab";
//There is no need for this keyword
tabs.push(<div className="tab-pane fade" id={id} role="tabpanel" aria-labelledby={aria}><EpisodeCards episodes={season}/></div>);
currentSeason++;
}
return (
<div className="tab-content py-3 px-3 px-sm-0" id="nav-tabContent">
{tabs}
</div>
)
}

how to replace image source in react?

Could you please tell me how to replace image source in react? .I am setting a src url to my img tag.
If image is not present on server I want to replace src url to this one http://punemirror.indiatimes.com/photo/55813567.cms
if image is present on server then it fine .if not then I need to change source url to "http://punemirror.indiatimes.com/photo/55813567.cms
"
here is my code
https://codesandbox.io/s/KOrGKp3B8
I try like that
imageExists(url, callback) {
var img = new Image();
img.onload = function () {
callback(true);
};
img.onerror = function () {
callback(false);
};
img.src = url;
}
renderList() {
const lis = this.items.map((item, key) => {
var src = "http://mumbaimirror.indiatimes.com/photo/" + item.id + ".cms";
const alt = "http://punemirror.indiatimes.com/photo/55813567.cms";
return (
<li key={key}>
<a><img src={src}/><span>{item.hl}</span></a>
</li>
)
})
return (
<ul>
{lis}
</ul>
)
}
render() {
return (
<div className="list">
{this.renderList()}
</div>
)
}
}
Check if your image exists, use this method and then in your component class :
componentWillMount() {
var url = "http://mumbaimirror.indiatimes.com/photo/" + item.id + ".cms";
const alt = "http://punemirror.indiatimes.com/photo/55813567.cms";
var src = this.imageExists(url) ? url : alt;
this.setState({ src });
}
// added from the mentioned post
function imageExists(image_url){
var http = new XMLHttpRequest();
http.open('HEAD', image_url, false);
http.send();
return http.status != 404;
}
render() {
var src = this.state.src;
...
}
You can use object for this.
<object data={src} type="image/png">
<img src="http://punemirror.indiatimes.com/photo/55813567.cms" />
</object>
On component render, you need to check server-side for all present files, and return an array of all file ids you got on the server.
When you get that array of existing files, let's call it allFileIds, you just need to do :
<li key={key}>
<a><img src={allFileIds.indexOf(item.id) !== -1 ? src : alt}/><span>{item.hl}</span></a>
</li>
This will check if the required id was found on the server (it checks if the item.id value exists in the array of file ids that your server returned), and if not, render the alt property instead of the src. I hope that was clear!
First put your image collection in state instead of field.
I assume each image in your images collection contains at least one field: url. You can check your images (this.items) for existence in componentDidMount/componentWillReceiveProps. Note that your imageExists method is async - therefore you cant use it during rendering. Based on the check you can set img.src to be either undefined/null or valid URL.
Then in render check image.url and if it is missing - use default one.

Resources