How to view an image in ReactJS from localhost - reactjs

I used PHPmyAdmin as my localhost, Axios to do backend functions and react to display on the webpage, I created a table that stores an ID and a Blob, since blob can store image data. I used state hooks and render each of the item to be displayed on the page but when I render the page, a broken image has displayed. I tried to console.log() on that image data and it displayed as {type: 'Buffer', data: Array(50639)} on the console browser.
In short, I am trying to retrieve an image from a table in the localhost and display it on the browser
React
function ProjectCard() {
const [projectCard, setProjectCard] = useState([]);
const instance = axios.create( {
baseURL: "http://localhost:3001/api",
});
useEffect(() => {
instance.get("/getAvailableProjects").then((response) => {
setProjectCard(response.data);
});
}, []);
return (
<div className="row g-4 py-4 border-bottom">
{projectCard.map((val) => {
return (
console.log(val.PROJECT_IMAGE) {/* displayed as {type: 'Buffer', data: Array(50639)} */}
<div className="col-lg-3 col-md-6 mb-2" key={val.PROJECT_ID}>
<img id="project-img" src={val.PROJECT_IMAGE} className="img-fluid" /> {/* BROKEN IMAGE */}
</div>
);
})}
</div>
)
};
export default ProjectCard;
Server
app.get("/api/getAvailableProjects", (req, res) => {
const sqlQuery = "SELECT *, from projectdetail";
db.query(sqlQuery, (_error, result) => {
res.send(result);
});
});
Is there a way to convert this blob data into an actual image?

Checkout this JS object:
<img src={URL.createObjectURL(file) alt="fooBar" />
It should look like this.
URL.createObjectURL: https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL

Related

How to get the URL/source of an image that has been attached and uploaded to MongoDB?(wysiwyg)

I am creating a blog-post website via markdown(with NEXTJS and Typescript) and the issue that I am currently facing is in the panel where the post is being created when image from /url or source from local machine/ is being submitted.
The panel does preview the image in the textarea element but once submitted to my MongoDB collection, what I get is an empty space in the place of the image. The packages that I am using are - react-draft-wysiwyg - which is the package that enables me to create content and providing me with the creation panel in markdown version and also the package that helps attach images - and for rendering I am using react-markdown - so I can be able to convert markdown to html - used along with remark-gfm as a plugin for the render.
So the question is how can I can also attach/get the url/source of the given image in markdown to my database collection while using react-draft-wysiwyg as apparently they doesn't respond much in their Github(https://github.com/jpuri/react-draft-wysiwyg/issues/1307)
Here is the my code for the creation panel of the blogpost
<Editor
wrapperClassName="demo-wrapper"
editorClassName="demo-editor"
contentState={contentState}
onEditorStateChange={(editorState) => {
setEditorState(editorState);
}}
toolbar={{
image: {
previewImage: true,
urlEnabled: true,
uploadEnabled: true,
uploadCallback: () => {
return new Promise((resolve, reject) => {
resolve({
data: { link: convertedData.entityMap[0].data.src },
});
});
},
},
}}
/>
<textarea
disabled
hidden
onChange={(e) => console.log(contentTextArea)}
value={
editorState &&
draftToMarkdown(
convertToRaw(editorState.getCurrentContent()),
{
entityItems: {
image: {
open: function (entity) {
console.log(entity);
return 'open';
},
close: function (entity) {
// #ts-ignore
console.log(entity);
return 'close';
},
},
},
}
)
}
/>
</div>
</div>
And that's how I am trying to render it
{result.map(
(post: any, index: React.Key | null | undefined) => {
return (
<>
<h4 key={index} className="text-2xl text-center pt-20">
{post.title}
</h4>
<ReactMarkdown
remarkPlugins={[gfm]}
className="text-left px-4"
>
{post.body}
</ReactMarkdown>
</>
);
}
)}
This is also what is submitted to my collection in Mongo while trooubleshooting
Hopefully I have managed to explain properly the trouble I'm facing,thank You in advance for the shared time and wisdom!

Disqus email notifications open localhost instead of the real website

I am using Gastbyjs with Disqus plugin for commenting function. I followed the instruction here
I received emails about comments in my blog, but when I clicked the button "Reply to XXX" it opens.
https://localhost:8000/blogs/article-name
I think I missed some configuration for this.
Update 1
Here is the code where I use the config:
export const BlogPostTemplate = ({
content,
contentComponent,
description,
tags,
title,
helmet,
}) => {
const PostContent = contentComponent || Content;
const disqusConfig = {
shortname: process.env.GATSBY_DISQUS_NAME,
config: { identifier: title },
};
Update 2
I managed to use Reach/Router to access Location
I installed reach/router and I updated my code:
import { Location } from "#reach/router";
export const BlogPostTemplate = ({
content,
contentComponent,
description,
tags,
title,
helmet,
location
}) => {
const PostContent = contentComponent || Content;
console.log('--------------location---------');
console.log(location);
const disqusConfig = {
url: location.href,
shortname: process.env.GATSBY_DISQUS_NAME,
config: { identifier: title },
};
return (
<section className="section">
{helmet || ""}
<div className="container content">
<div className="columns">
<div className="column is-10 is-offset-1">
<h1 className="title is-size-2 has-text-weight-bold is-bold-light">
{title}
</h1>
<p>{description}Cool</p>
<PostContent content={content} />
{tags && tags.length ? (
<div style={{ marginTop: `4rem` }}>
<h4>Tags</h4>
<ul className="taglist">
{tags.map((tag) => (
<li key={tag + `tag`}>
<Link to={`/tags/${kebabCase(tag)}/`}>{tag}</Link>
</li>
))}
</ul>
</div>
) : null}
<DiscussionEmbed {...disqusConfig} />
</div>
</div>
</div>
</section>
);
};
const BlogPost = ({ data }) => {
const { markdownRemark: post } = data;
return (
<Layout>
<Location>
{({ location }) => (
<BlogPostTemplate
content={post.html}
contentComponent={HTMLContent}
description={post.frontmatter.description}
helmet={
<Helmet titleTemplate="%s | Blog">
<title>{`${post.frontmatter.title}`}</title>
<meta
name="description"
content={`${post.frontmatter.description}`}
/>
</Helmet>
}
tags={post.frontmatter.tags}
title={post.frontmatter.title}
location={location}
/>
)}
</Location>
</Layout>
);
};
However, when someone left a comment and I click the "Reply to {somebody}" button in the notification email, it still opens the localhost, rather than the real website link.
I finally figured it out. I'd like to break the answer into 4 parts:
How does the localhost url sneak into the comment's url?
The localhost url sneaked into the comment's url when I was commenting my article in a localhost development environment.
So to prevent this from happening again, only posting a comment in the production environment. If you did it in localhost environment, how to fix it? Please look at point 3.
What does localhost url is called?
The comment url is called Discussion Url.
Why do we need to know it?
Because this will be the key words for searching any related questions/answers. Without knowing this, I have wasted days for searching this configuration in Disqus.
So in short, it saves you tremendous time.
How and where to solve it?
As you can see there, the 2nd blog Link was using localhost, after I updated to the real website url, the problem was solved.
Hope my answer is helpful.
You need to pass the url to the disqusConfig of the current page disqus is located. In Gatsby, you can expect the location prop to be available to you on every page thanks to its use of #reach/router.
In your component:
import {Disqus} from "gatsby-plugin-disqus";
const Article = (props) => {
let disqusConfig = {
url: props.location.href,
identifier: props.your.identifier.source,
title: props.your.title.source,
};
return (
<div className="article">
<h1>Article title</h1>
<div>Article text</div>
<Disqus config={disqusConfig} />
</div>
)
}
Plugin config:
{
resolve: `gatsby-plugin-disqus`,
options: {
shortname: `your-short-name`
}
}
Note: you can't use something like window.location because there is no window during build time (there is no browser server side).

URL Image only shows when browser resized

I am using React.js and firebase. I am fetching an image from firebase and trying to render it in a component.
When the image URL is available, I setState the URL, but the image still does not show.
componentDidMount(){
const that = this;
firebase
.storage()
.ref("hero1.png")
.getDownloadURL()
.then(url => {
console.log(url);
that.setState({url})
})
.catch(error => {
// Handle any errors
});
}
// rendering the image
...
{ this.state.url &&
this.state.slides.map((slide, index) => {
console.log(slide.imageUrl); // url is being printed here
return (
<div
key={index}
onDragStart={this.handleOnDragStart}
className="slider-wrapper"
>
<div key={index} className="slider-content">
<img src={this.state.url} /> // when I set a hard-coded url, it works, but
//does not work in state
</div>
</div>
);
})}
...
One more thing, when I resize the browser, the image shows up immediately. Don't know why
Try this one, I removed key from the child div and updated the other key to slide.imageUrl:
{ this.state.url &&
this.state.slides.map((slide, index) => {
console.log(slide.imageUrl); // url is being printed here
return (
<div
key={slide.imageUrl}
onDragStart={this.handleOnDragStart}
className="slider-wrapper"
>
<div className="slider-content">
<img src={this.state.url} /> // when I set a hard-coded url, it works, but
//does not work in state
</div>
</div>
);
})}
I was using a library (react-alice-carousel) to render the slides of images. This was causing problem. Just switched the library to react-animated-slider, and it worked.
Thanks, everybody for helping me and for your time.

How to use a variable (a URL saved as a string) from another component?

Question: How can I use different URLs from different components in a third component as one ?
I am learning React.js and I would like to make multiple pages. This is an example project for learning purposes. There is one page where I can see the images and info of TeamA and there is another page where I can see the images and info of TeamB.
In order to avoid duplicates, I want to separate small components. I have a Card component which displays the image of team members with name and info. I want to use this one Card component for the page TeamA and also for the page TeamB.
The only difference now is the URL for the images - there is 1 URL for TeamA and one for TeamB. It should change accordingly.
I hope I could describe the problem. Please see the code examples below.
I appreciate your help. Have a nice day!
1st Component which has a unique URL for images:
const TeamA = ({id}) => {
const exampleImages = `https://url`;
return (
<div>
<Teams>
<Card teamImg={exampleImages}/>
</Teams>
</div>
);
}
2nd Component which also has a unique URL for images:
const TeamB = ({id}) => {
const exampleImagesB = `https://url`;
return (
<div>
<Teams>
<Card teamImg={exampleImagesB}/>
</Teams>
</div>
);
}
The Component that displays the information of the Team component (above). In this component, I want to use the URLs from the other components and add it to the img tag.
const Card = ({ name, email, id, teamImg }) => {
return (
<div className='tc'>
<img alt='image' src={`${teamImg}`}/>
<div>
<h2>{name}</h2>
<p>{info}</p>
</div>
</div>
);
}
You can make team a functional component of it's own:
const Team = ({id, imageUrl}) => {
return (
<div>
<Teams>
<Card teamImg={imageUrl}/>
</Teams>
</div>
);
}
Then you can pass imageUrl into your teams at a higher level without writing them out as separate components each time.
For example if you have your different urls as an array, this could be the component above team:
const AllTeams = () => {
const images = [{ id: 1, url: 'url1' }, { id: 2, url: 'url2' }];
return (
<>
{ images.map(image => <Team key={image.id} imageUrl={image.url} />) }
</>
);
}

Passing data via props and using array.map not working

I'm currently building app and am using the firebase for data storage, and am having an issue spreading the same data to the two different components( for example: AllProjects and SelectedProject) once the user is logged in.
In the first component(AllProjects), it works and am able to map through the data array and build cards that I want to use for navigating to the second component(SelectedProject). But when I map the same data array again, to spread its content to SelectedProject component(to each individual project), the map is not working and only the data from the first project in the array is being passed to each other project.
function UserPanel(props) {
const [projects, setProjects] = useState([]);
//get data from firebase
useEffect(() => {
return db
.collection("users")
.doc(`${props.user.uid}`)
.collection("projects")
.onSnapshot(snapshot => {
const docs = [];
snapshot.forEach(doc => {
docs.push({
...doc.data()
});
});
setProjects(docs);
});
}, [props.user.uid]);
return (
<div>
<Nav user={props.user} />
<Router>
<AllProjects projects={projects} path="/" />
{projects.map(project => (
<SelectedProject
project={project}
path="projects/:projectId"
key={project.id}
/>
))}
</Router>
</div>
);
}
export default UserPanel;
First Component
function AllProjects(props) {
return (
<div>
{props.projects.map(projects=> (
<Link key={projects.id} to={`/projects/${projects.id}`}>
<ProjectCard projects={projects} />
</Link>
))}
</div>
);
}
I was not able to find the solution for spreading all data dynamically through the app(even not sure now if it's possible?) but rather making a second API call from inside the second component and using id from the router path to select the desired project.

Resources