Gatsby: Set up react-share component into blog posts

Created on 18 Jan 2018  ·  19Comments  ·  Source: gatsbyjs/gatsby

Description

I implemented react-share component in order to share blog post on social network such as Facebook or Twitter but I can't get the current url of the page. I set const shareUrl = location.pathname; but this URL doesn't appear when I share the post on Twitter (for example).

reseauxsociaux
I get URL de la page :/conseils/bonjour-tout-le-monde blog-post.js:39 when I do a console.log('URL de la page :'+location.pathname);.

Environment

Gatsby version: 1.1.27
Node.js version: 8.9.3
Operating System: OSX El Capitan

Code

import React from 'react'
import Helmet from 'react-helmet'
import Img from 'gatsby-image'
import Link from 'gatsby-link'
import {
  ShareButtons,
  ShareCounts,
  generateShareIcon
} from 'react-share';

const {
  FacebookShareButton,
  GooglePlusShareButton,
  LinkedinShareButton,
  TwitterShareButton,
  EmailShareButton,
} = ShareButtons;
const {
  FacebookShareCount,
  GooglePlusShareCount,
  LinkedinShareCount,

} = ShareCounts;

const FacebookIcon = generateShareIcon('facebook');
const TwitterIcon = generateShareIcon('twitter');
const GooglePlusIcon = generateShareIcon('google');
const LinkedinIcon = generateShareIcon('linkedin');

const EmailIcon = generateShareIcon('email');

export default function Template({
  data, location // this prop will be injected by the GraphQL query we'll write in a bit
}) {
  const { markdownRemark: post } = data;
  const shareUrl = location.pathname;
  const title = post.frontmatter.title; 
  return (
    <div className="blog">
      <div className="content">
        <Helmet title={`Auto contrôle des Hexagones | Conseils - ${post.frontmatter.title}`} />
        <Img sizes={post.frontmatter.image.childImageSharp.sizes} />
        <div className="blog-post">
          <p> Publi&eacute; le {
            post.frontmatter.date
          } </p>
           <ul className="social-share">
            <li>
                <FacebookShareButton
                url={shareUrl}
                quote={title}
                className="button" 
                >
                <FacebookIcon
                  size={32}
                  round={false} />
              </FacebookShareButton>

              <FacebookShareCount
                url={shareUrl}
                className="count">
                {count => count}
              </FacebookShareCount>
            </li>
            <li>
                <TwitterShareButton
                url={shareUrl}
                title={title}
                className="button">
                <TwitterIcon
                  size={32}
                  round={false} />
              </TwitterShareButton>
            </li>
            <li>
                <GooglePlusShareButton
                url={shareUrl}
                className="button">
                <GooglePlusIcon
                  size={32}
                  round={false} />
              </GooglePlusShareButton>

              <GooglePlusShareCount
                url={shareUrl}
                className="count">
                {count => count}
              </GooglePlusShareCount>
            </li>
            <li>
                <LinkedinShareButton
                url={shareUrl}
                title={title}
                windowWidth={750}
                windowHeight={600}
                className="button">
                <LinkedinIcon
                  size={32}
                  round={false} />
              </LinkedinShareButton>

              <LinkedinShareCount
                url={shareUrl}
                className="count">
                {count => count}
              </LinkedinShareCount>
            </li>
            <li>
              <EmailShareButton
              url={shareUrl}
              subject={title}
              body="body"
              className="button">
              <EmailIcon
                size={32}
                round={false} />
              </EmailShareButton>

            </li>
          </ul>
          <div
            className="blog-post-content"
            dangerouslySetInnerHTML={{ __html: post.html }}
          />

        </div>
      </div>
      <Helmet
        bodyAttributes={{
          class: 'noBgImg'
        }}
      />
    </div>
  );
}
export const pageQuery = graphql`
  query BlogPostByPath($path: String!) {
    markdownRemark(frontmatter: { path: { eq: $path } }) {
      html
      frontmatter {
        date(formatString: "DD MMMM YYYY", locale:"fr")
        path
        title
        image {
          childImageSharp {
            resize(width: 1500, height: 1500) {
              src
            }
            sizes(maxWidth: 786) {
              ...GatsbyImageSharpSizes
            }
          }
        }    


      }
    }
  }
`;


Expected behavior

I want to the URL appears right next to the title of the article

Thanks for helping. I tried to post on react-share git repo, but the community is not that active.

question or discussion

Most helpful comment

Oh looking at your original component code, you've destructured location already so you should be able to use just location.pathname.

All 19 comments

Hey @MaralS, location.pathname will only give you the pathname ;-) of the current page, e.g. for https://www.gatsbyjs.org/blog/ this would be /blog/.

You'll want to include the protocol (https:), the slashes after it (//) and the hostname (www.gatsbyjs.org), too: location.href should give you all of that.

@fk thank you for the quick answer :)
There is no other way to get the current hostname ?

See my previous comment – try const shareUrl = location.href; instead of const shareUrl = location.pathname;.

@fk Sorry I'm a little tired XD
Thank you so much :)

No worries! Let us know if that worked!

@fk location.hrefis not working, I can't even click on my twitter button :/

The console considers as location.hrefas undefined
But if i'm doing :

const hostname = 'autocontrole-beta.netlify.com';
const shareUrl = 'http://'+hostname+location.pathname;

It's working but I want to find a cleaner way to do this xD

My bad, location.href only works in development (also I little tired I guess 🙄😉). For production you need this.props.location. One more hurdle is that in production you don't have access to this.props.location.href, so I'd suggest just hardcoding the protocol + hostname like this:

const shareUrl = `https://www.example.com${this.props.location.pathname}`;

If you require the protocol + hostname anywhere else and would like a single source of truth, you can use the siteUrl field in gatsby-config.js like in https://github.com/gatsbyjs/gatsby/blob/53c05d087218982cb157712b118dd9387bc1783d/www/gatsby-config.js#L4

and then query that field with GraphQL.

When I replace by const shareUrl =https://www.example.com${this.props.location.pathname}; I get this error

TypeError: Cannot read property 'location' of undefined
new Template
src/templates/blog-post.js:41
  38 | // const shareUrl = 'http://'+hostname+location.pathname;
  39 |  const title = post.frontmatter.title; 
  40 |  console.log('URL de la page :'+location.pathname);
> 41 |  const shareUrl = `https://www.example.com${this.props.location.pathname}`
  42 |  return (
  43 |    <div className="blog">
  44 |      <div className="content">

Ayayay … I guess that's happening when you do a gatsby build?

location.pathname will only work for gatsby develop, for gatsby build this needs to be this.props.location.pathname (which works for both).

Before I send you down the wrong path again – is the source for your site publicly available somewhere so I can take a look?

@fk yes I put the repo on public mode https://github.com/MaralS/autocontrole
Thanks a lot 🙂

Took a look and updating Gatsby to the latest version (or rm yarn.lock && yarn) resolves the problem – you had v1.9.157 in your yarn.lock, things work fine with 1.9.159 again! 👍

Let me know when I can delete my fork!

I still have this error

×
TypeError: Cannot read property 'location' of undefined
new Template
src/templates/blog-post.js:38
  35 | }) {
  36 |   const hostname = 'autocontrole-beta.netlify.com';
  37 |   const { markdownRemark: post } = data;
> 38 |   const shareUrl = `https://www.example.com${this.props.location.pathname}`;
  39 |   const title = post.frontmatter.title; 
  40 |   console.log('URL de la page :'+location.pathname);
  41 |   return (

It only works when I'm doing
'https://www.example.com'+location.pathname

Maybe I'm doing something wrong xD

@MaralS try props.location instead of this.props.location :-)

this doesn't exist in functional components

When I try props.location I get ReferenceError: props is not defined -_-'

Oh looking at your original component code, you've destructured location already so you should be able to use just location.pathname.

Thanks for jumping in @KyleAMathews.
@MaralS I forked your repository yesterday (https://github.com/fk/autocontrole) and bumped the Gatsby version in this commit: https://github.com/fk/autocontrole/commit/cb7f328af702c1e9354f41c56227a1cd2946ff37

With the update, your original, unaltered code is working fine for me.

Thank you, so i think you can unfork the repo @fk :)

Just deleted my fork! Hope things are working for you now!?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rossPatton picture rossPatton  ·  3Comments

mikestopcontinues picture mikestopcontinues  ·  3Comments

theduke picture theduke  ·  3Comments

signalwerk picture signalwerk  ·  3Comments

3CordGuy picture 3CordGuy  ·  3Comments