how to replace image source in react? - reactjs

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.

Related

How can I create a parent html element by appending sub element from an object?

In my react app I need to return a line which will be created based on a list.
Here is the object,
searchCriteria: {
op_company: "039",
doc_type: "ALL"
}
and in my UI, i need to show it as a paragraph with bold values. So the hard coded code would be like below
<p>Download request for op_company: <b>{searchCriteria.op_company}</b>, doc_type: <b>{searchCriteria.doc_type}</b></p>
But the object(searchCriteria) will be changed based on the user request. So I tried like below.
const getSearchCriteria = (criteria) => {
let searchCriteria = []
searchCriteria.push('Download request for')
Object.keys(criteria).forEach((key) => {
if(criteria[key] !== '') {
searchCriteria.push(` ${key}: ${criteria[key]},`)
}
});
return searchCriteria;
}
return (
<p>
{getSearchCriteria(searchCriteria).map((item) => <span key = {item}>{item}</span>)}
</p>
);
here i'm getting the expected output. But I can't get the value as bold (highlighted). Is there another way to directly deal with html elements?

I am getting a void returned when trying to dynamically import images from a directory using webpack

For context, I was reviewing Dynamically import images from a directory using webpack
When trying to use the importAll(i) function,
It seems that my images object does not get populated and/or the images object is undefined.
Can anyone help as to where I am going wrong?
function importAll(i) {
let images = {};
i.keys().map((item, index) => {images[item.replace('./', '')] = i(item);
return images;
});
}
const images = importAll(require.context('../images', false, /\.png$/));
<img src={ images['chatLogo.png'] } alt="Chat Logo" width="300" height="250" />
My file directory:
I've got it in the components folder as I was trying to figure out if it was my filepath that was the issue.
Your importAll function doesn't return images, your map function does. You need to move a } up so the return statement is in the outer function.
Formatted for clarity, but otherwise unmodified:
function importAll(i) {
let images = {};
i.keys().map((item, index) => {
images[item.replace('./', '')] = i(item);
return images; // <-- this should be outside the map function
});
// return images; <-- should be here
}

React If / else for picture src

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]}/>

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

React application slow performance

I am trying to make a application in react for rendering a tree like structure which can be expanded and collapsed on user input, although i have managed to get the app working as I want but the performance is quite slow. I am not sure if this is because of the nature of the application, the react component or my ignorance of the framework.
I have done a chrome profiling and here are the screenshots:
Please if you can help me understand through this images what is the bottleneck and if/how it can be solved.
Source :
https://github.com/harsh-a1/react-skeleton/tree/tree
Component :
export function TreeComponent(props){
var instance = Object.create(React.Component.prototype)
var state = {
previousSelected :{},
onSelectCallback : props.onSelectCallback
}
instance.props = props;
var toggle = function(){
instance.setState(state.data)
}
instance.updateState = function(){
instance.setState(Object.assign({},state))
}
if (!props.data){
init(function(ous){
state.data = ous;
instance.setState(state)
});
}
instance.render = function(){
if (!state.data){return <div key = "dummy"></div>}
return <ul key={"ul_"+state.data.id}>
<Tree data={state.data} updateState={instance.updateState} state={state } />
</ul>
}
return instance;
function Tree(props){
var instance = Object.create(React.PureComponent.prototype)
instance.render = function(){
if (!props.data.children || props.data.children.length == 0){
return (
<li key={"li_"+props.data.id}>
<LeafNode data={props.data} updateState = {props.updateState} state={props.state} />
</li>
)
}
return (
<li key={"li_"+props.data.id}><LeafNode data={props.data} updateState = {props.updateState} state={props.state} />
<ul key = {"ul_"+props.data.id} style={props.data.showChildren?{"display":"inline"}:{"display":"none"}}>
{
props.data.children.map(function(child){
return <Tree data={child} key={"tree_"+child.id} updateState = {props.updateState} state={props.state} />
})
}
</ul></li>
)
}
return instance;
function LeafNode(props){
var instance = Object.create(React.PureComponent.prototype)
instance.props = props;
/* instance.shouldComponentUpdate = function(nextProps) {
return (nextProps.data.showChildren !== this.props.data.showChildren);
}
*/
instance.componentDidMount= function(){
console.log("yes")
}
instance.toggle = function(){
props.data.showChildren = !props.data.showChildren;
props.updateState();
}
instance.selected = function(){
props.state.previousSelected.selected = false;
props.data.selected = !props.data.selected;
props.state.previousSelected = props.data;
props.updateState();
props.state.onSelectCallback(Object.assign({},props.data));
}
instance.render = function(){
var toggleImg = "";
if ( props.data.children.length!=0){
toggleImg = props.data.showChildren ?expandIMG:collapseIMG;
}
return (
<div key={"div_"+props.data.id} >
<span key={"span_"+props.data.id} className="toggle" >
<img key={"img_"+props.data.id} width="12" height="12" src={toggleImg} onClick={instance.toggle} />
</span>
<a key={"a_"+props.data.id} onClick = {instance.selected} style={props.data.selected? {color:"yellow"}:{color:"black"}} >{props.data.name}</a>
</div>
)
}
return instance
}
}
}
Thanks
harsh
Have a look at best practices how to create components and component lifecycle at React website. It is a good idea to follow them so it would be easier to identify problems later.
It is also worth looking at react-virtualized components. There are a bunch of components that could be reused including list, grid, tree etc. Also look at their implementation since it is opensource.
Their virtual list component resolved my issue with rendering 500+ items.
Here is an example with 1M+ nodes and good performance. The trick is to use local state and not render the hidden elements.
https://codesandbox.io/s/z6jr6zww4l
Turns out The issue was that I was using the "development" build to check it....i switched to a production library and now it is running not to bad...still not as good as direct DOM but pretty close...although don't know how much it can scale...

Resources