How to display an svg image in reactjs - node.js

I am working on a web application with Nodejs and Reactjs and currently i'm retrieving data from the mongo database and displaying it with react.
Here is some code :
import React, {Component} from 'react';
import axios from '../../node_modules/axios';
import {Col,Card} from 'react-bootstrap';
import {BrowserRouter as Router,Link, useRouteMatch} from 'react-router-dom';
const Brand = props => (
<Col lg="4" className="d-inline-block">
<Link to="/admin/Marques/MarqueDetails/1">
<Card className="marque-card" style={{ width: '100%' }}>
<p>{props.brand.name}</p>
<Card.Img className="marque-card" variant="top" src={`../../public/` +
props.brand.imgUrl} />
</Card>
</Link>
</Col>
)
class cardBrand extends Component {
constructor(props) {
super(props);
this.state = {brands: []};
}
componentDidMount() {
axios.get('http://localhost:5000/brand/')
.then(response => {
this.setState({ brands: response.data })
})
.catch((error) => {
console.log(error);
})
}
brandList() {
return this.state.brands.map(currentBrand => {
return <Brand brand={currentBrand} key={currentBrand._id}/>;
})
}
render() {
return(
<Col lg="12">
{ this.brandList() }
</Col>
)
}
}
export default cardBrand;
As you can see i have the img/brand folders inside the public folder and the props.brand.imgUrl contains the path and the image name, but unfortunately it's not working on the browser, here is an image :
P.S : i already tried react-svg but nothing happened, maybe because i didn't know how to use it.
Thank you in advance.

From the screenshot, looks like your svg path is img/brand/svg-name.svg. to display the image don't include public in your source. for example, to display images in public/img/brand you use
// without specifying public directory
<img alt="test" src={'/img/brand/svg-name.svg'}/>
Change your card src to
<Card.Img className="marque-card" variant="top" src={`/${props.brand.imgUrl}`} />

Related

Using express js I can't render items on screen. It goes blank. Full stack

I am using express nodejs to create a fullstack app, this page has to show users and products but it is rendering a blank page. If I delete the {} of user, it renders the page but with no results.
import React, { useContext, useState } from 'react';
import CoffeeContext from '../contexts/CoffeeContext';
import { Link } from "react-router-dom";
import '../App.css'
import UserContext from '../contexts/UserContext';
function CoffeeList(props) {
let { deleteCoffee } = useContext(CoffeeContext);
let { user } = useContext(UserContext)
return (
<CoffeeContext.Consumer>
{
({ coffee }) => {
return <div>
<h1>Posts</h1>
<h4>Hello <span> {user.username}'Insert user's name here' Thanks for visiting our website!</span></h4>
<button>Add New Post</button>
<div>
{coffee.map((c) => {
console.log(coffee)
return (
<div key={c._id}>
<h2>{c.name}</h2>
<Link to={`/edit/${c._id}`}>
<button>Edit</button>
</Link>
<button onClick={() => { deleteCoffee(c._id)}}>Delete</button>
<h6>{user.username}</h6>
</div>
)
})}
</div>
</div>
}
}
</CoffeeContext.Consumer>
);
}
export default CoffeeList;

how to pass a link to another components in react

I am trying to pass a Link it has a films id to another component named movie detail js.
the problem I am having is connecting Movies Container link to movie detail. Please help
MoviesContainer.js
<Link to={ `/movie/${films.id}${config.apiKey}` }>
<button className='successW' > GET INFO </button>
</Link>
MovieDetail.js
import React, { Component } from 'react';
import axios from 'axios';
import './MovieDetail.css';
import { props , match , params, } from 'react-router-dom';
//import config from '../../config.js';
import films from '../MoviesContainer/MoviesContainer.js';
import router from '../../router.js'
export default class MovieDetail extends Component{
constructor(props){
super(props);
this.state= {
movie:[]
}
}
componentWillMount(){
axios.get(`/movies/:id`).then(response=> {
console.log(response.data.results);
this.setState({ moviesList: response.data.movie });
});
}
render(){
console.log( this.setState.movie);
const imgURL= 'http://image.tmdb.org/t/p/original';
return(
<div className='moviecd'>
<img style={{ height: '85%', width: '100%' }} src={ imgURL + this.state.movie.poster_path } alt='movie poster'></img>
</div>
)
}
}
ı guess you are using React-Router. First of all, you can specify the path you will use in the Router system and which component should be installed if this path is used. For Example :
<Route exact path="/movies/:movieId" component={MovieDetails} />
This is the system you should use for your router.
and there is a button to go to the MovieDetails.js component.
you should wrap this button with a Link(React-Router). Like This:
<Link to = {{pathname: `${movieId}`}}> // The id of the movie you clicked
<button>Go Movie </button>
</Link>
Now, if you clicked on which movie you clicked on, the id of that movie will go to the MovieDetails.js component as a props.
If you browse the props coming to the MovieDetails component, you will find a props like params.match.movieId.
You can now use this id when making a request (Inside the MovieDetails component). Like This:
fetch(`https://api.themoviedb.org/3/movie/${this.props.match.params.movieId}?api_key=<yourapikey>`)
How you process it after you get the data is up to you!
I hope it was understandable. Good Luck !

Nextjs how to not unmount previous page when going to next page (to keep state)

we are using Nextjs in our web app.
We want to keep stack of pages where users visit to keep state of component on back navigation.
How should we do that?
I have tried https://github.com/exogen/next-modal-pages, but it calls getInitialProps of previous pages again on back.
Here's my solution with a custom _app.js
import React, { useRef, useEffect, memo } from 'react'
import { useRouter } from 'next/router'
const ROUTES_TO_RETAIN = ['/dashboard', '/top', '/recent', 'my-posts']
const App = ({ Component, pageProps }) => {
const router = useRouter()
const retainedComponents = useRef({})
const isRetainableRoute = ROUTES_TO_RETAIN.includes(router.asPath)
// Add Component to retainedComponents if we haven't got it already
if (isRetainableRoute && !retainedComponents.current[router.asPath]) {
const MemoComponent = memo(Component)
retainedComponents.current[router.asPath] = {
component: <MemoComponent {...pageProps} />,
scrollPos: 0
}
}
// Save the scroll position of current page before leaving
const handleRouteChangeStart = url => {
if (isRetainableRoute) {
retainedComponents.current[router.asPath].scrollPos = window.scrollY
}
}
// Save scroll position - requires an up-to-date router.asPath
useEffect(() => {
router.events.on('routeChangeStart', handleRouteChangeStart)
return () => {
router.events.off('routeChangeStart', handleRouteChangeStart)
}
}, [router.asPath])
// Scroll to the saved position when we load a retained component
useEffect(() => {
if (isRetainableRoute) {
window.scrollTo(0, retainedComponents.current[router.asPath].scrollPos)
}
}, [Component, pageProps])
return (
<div>
<div style={{ display: isRetainableRoute ? 'block' : 'none' }}>
{Object.entries(retainedComponents.current).map(([path, c]) => (
<div
key={path}
style={{ display: router.asPath === path ? 'block' : 'none' }}
>
{c.component}
</div>
))}
</div>
{!isRetainableRoute && <Component {...pageProps} />}
</div>
)
}
export default App
Gist - https://gist.github.com/GusRuss89/df05ea25310043fc38a5e2ba3cb0c016
You can't "save the state of the page by not un-mounting it" but you can save the state of your app in _app.js file, and the rebuild the previous page from it.
Check the redux example from next's repo.

How to display images in Bootstrap carousel using React

So I have a component(Posts) in which a loop through all the posts from the Database. In the component, I 'embedded' another component(PostItem) so I dont have to create a different component for viewing individual entries. Now inside the PostItem component I have another component with the name of 'PostGallery'.
This is the current code that I have in PostItem.js file:
import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import PostGallery from '../posts/PostGallery';
const PostItem = ({
post: { _id, text, name, files, avatar, user, likes, comments, date },
}) => (
<article className={_id}>
<Link to={`/posts/${_id}`}>
<div id="carouselExampleIndicators" className="carousel slide" data-ride="carousel">
<div className="carousel-inner">
{files.slice(0, 5).map((file, index) => (
<PostGallery key={index} post={file} />
))}
</div>
</div>
</Link>
</article>
);
PostItem.propTypes = {
post: PropTypes.object.isRequired,
};
export default connect(
null, null
)(PostItem);
When posting an entry the user can post URL from images separated by comma which is working just fine. The problem comes when displaying it in the front-end.
This is what I have in my PostGallery component:
import React from 'react';
import PropTypes from 'prop-types';
const PostGallery = ({
post: { files }
}) => {
return (
<div className="">
{post.files.length > 0 ? (
post.files.map(file => (
<img key={file} src={file} alt="" />
))) : (
<p>No images found</p>
)
}
</div>
);
};
PostGallery.propTypes = {
post: PropTypes.object.isRequired,
};
export default PostGallery;
I believe this should be easy but somehow its just now working and the console it's not trowing me any errors related to it. So if you guys can help...
Thanks!

Cannot read property 'allContentfulBlogPost' of undefined" after moving query from index.js to component in GatsbyJS (with Contenful and GraphQL)

Moving a query from index.js to midsection.js (a component) gives Cannot read property of undefined.
I made a website with GatsbyJS which gets it's content from Contentful. I accomplished this by following the Build a blazing fast website with GatsbyJS and Contentful tutorial: https://www.youtube.com/watch?v=wlIdop5Yv_Y
In the tutorial you learn the basics of making a query which shows your content from Contentful on the homepage.
Because I like to use Bulma and I'm pretty new to GatsbyJS (new to React as well) I decided to download the Gatsby-Bulma-Quickstart (https://www.gatsbyjs.org/starters/amandeepmittal/gatsby-bulma-quickstart) and compare it to my own website and use what I need.
I decided to use the component structure used in the Quickstart and wanted to move the query for getting my content from the index.js to the midsection.js.
I got everything working until I moved the query.
My index.js looked like this:
import React from 'react'
import { Link } from 'gatsby'
// import Layout from '../components/layout';
const BlogPost = ({node}) => {
return (
<li>
<Link to={node.slug}><h3>{node.title}</h3></Link>
<img src={node.heroImage.resize.src} />
<div>{node.description.childMarkdownRemark.excerpt}</div>
</li>
)
}
const IndexPage = ({data}) => (
<ul className='blog-post'>
{data.allContentfulBlogPost.edges.map((edge) => <BlogPost node={edge.node} />)}
</ul>
)
// const IndexPage = () => <Layout />;
export default IndexPage
export const pageQuery = graphql`
query pageQuery {
allContentfulBlogPost (filter: {
node_locale: {eq: "en-US"}
},
sort:{ fields: [publishDate], order: DESC }
) {
edges {
node {
title
slug
description {
childMarkdownRemark {
excerpt
}
}
heroImage {
resize(width: 300, height: 300) {
src
}
}
}
}
}
}
`
Note: This works, this shows my content. (But as you can see the components etc from the Quickstart are not included (yet))
This is what my index.js looks like right now:
import React from 'react'
import Layout from '../components/layout';
const IndexPage = () => <Layout />;
export default IndexPage
And this is what my midsection.js looks like right now:
import React from 'react'
import { Link } from 'gatsby'
import './style.scss'
const BlogPost = ({node}) => {
return (
<li>
<Link to={node.slug}><h3>{node.title}</h3></Link>
<img src={node.heroImage.resize.src} />
<div>{node.description.childMarkdownRemark.excerpt}</div>
</li>
)
}
const Midsection = ({data}) => (
<ul className="blog-post">
{data.allContentfulBlogPost.edges.map((edge) => <BlogPost node={edge.node} />)}
</ul>
)
export default Midsection
export const pageQuery = graphql`
query pageQuery {
allContentfulBlogPost (filter: {
node_locale: {eq: "en-US"}
},
sort:{ fields: [publishDate], order: DESC }
) {
edges {
node {
title
slug
description {
childMarkdownRemark {
excerpt
}
}
heroImage {
resize(width: 300, height: 300) {
src
}
}
}
}
}
}
`
Using this way of moving the query to a component gives this error in the browser:
TypeError: Cannot read property 'allContentfulBlogPost' of undefined
I'd expected to use the midsection.js component for columns to show available "blog posts" from Contentful. Instead this only works straight from index.js.
Is there some way the query is not working because I moved it from the root folder to the components folder? And if so, what do I need to do to get the result I want?
With an colleague helping me, we found an solution by following these steps:
Change layout.js to:
import './style.scss'
const Layout = ({ children }) => children
export default Layout
Change index.js to:
import React from 'react'
import Layout from '../components/layout';
import Helmet from '../components/helmet';
import Header from '../components/header';
import Midsection from '../components/midsection';
import Footer from '../components/footer';
const IndexPage = ({data}) => (
<Layout>
<Helmet />
<Header />
<Midsection posts={data.allContentfulBlogPost.edges}/>
<Footer />
</Layout>
)
export default IndexPage
export const pageQuery = graphql`
query pageQuery {
allContentfulBlogPost (filter: {
node_locale: {eq: "en-US"}
},
sort:{ fields: [publishDate], order: DESC }
) {
edges {
node {
title
slug
description {
childMarkdownRemark {
excerpt
}
}
heroImage {
resize(width: 300, height: 300) {
src
}
}
}
}
}
}
`
Change midsection.js to:
import React from 'react'
import Link from 'gatsby-link'
import './style.scss'
const BlogPost = ({node}) => {
return (
<li>
<Link to={node.slug}><h3>{node.title}</h3></Link>
<img src={node.heroImage.resize.src} />
<div>{node.description.childMarkdownRemark.excerpt}</div>
</li>
)
}
const Midsection = ({ posts }) => (
<ul className="blog-post">
{posts.map(post => (
<BlogPost key={post.node.slug} node={post.node} />
))}
</ul>
)
export default Midsection
So what was the problem and what solved it?
The query used in this situation is a pageQuery which means that it only works from pages found in the pages folder. If you want to use the data in a component you have to pass it through :)

Resources