loading...
Cover image for Wordpress with React and Apollo

Wordpress with React and Apollo

teaglebuilt profile image dillan teagle Updated on ・3 min read

Ive decided to tryout React with GraphQL, Apollo, and Wordpress.

Repo: https://github.com/teaglebuilt/teaglebuilt.com

index.js


import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { ApolloClient } from 'apollo-boost';
import { createHttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { BrowserRouter } from 'react-router-dom';
import { ApolloProvider } from 'react-apollo';
import Config from './config';


const client = new ApolloClient({
    link: createHttpLink({
      uri: Config.gqlUrl,
    }),
    cache: new InMemoryCache(),
  });


ReactDOM.render(
    <BrowserRouter>
        <ApolloProvider client={client}>
            <App />
        </ApolloProvider>
    </BrowserRouter>,
    document.getElementById('root')
);

App.js

import React from 'react';
import { Switch, Route } from 'react-router-dom';
import Home from './components/Home';
import Header from './components/Header';
import Sidebar from './components/Sidebar';
import Page from './components/Page';
import Post from './components/Post';
import Category from './components/Category';
import Tagbar from './components/Tagbar';
import Tag from './components/Tag';
import './styles/index.css';


export default () => (
  <div className="">
    <Header />
    <div className="container w-full flex flex-wrap mx-auto px-2 pt-8 lg:pt-16 mt-16">
    <Sidebar />
      <Switch>
        <Route exact path="/" component={Home} />
        <Route exact path="/page/:slug" component={Page} />
        <Route exact path="/post/:slug" component={Post} />
        <Route exact path="/category/:slug" component={Category} />
        <Route exact path="/tag/:id" component={Tag} />
      </Switch>
    <Tagbar />
    </div>
  </div>
);

Tagbar.js

import React, { Component } from 'react';
import { withApollo } from 'react-apollo';
import { Link } from 'react-router-dom';
import gql from 'graphql-tag';


const TAGS_QUERY = gql`
    query {
        tags {
        edges {
            node {
            id
            link
            name
            slug
            posts {
                edges {
                node {
                    id
                }
                }
            }
            }
        }
        }
    }
`;


class Tagbar extends Component {
    constructor(props){
        super(props);
        this.state = {
            tags: []
        }
    }

    componentDidMount(){
        this.executeTagsQuery();
    }

    executeTagsQuery = async () => {
        const { client } = this.props;
        const result = await client.query({
            query: TAGS_QUERY
        })
        let tags = result.data.tags.edges;
        this.setState({
            tags: tags
        })
    }

    render(){
        const { tags } = this.state;
        return(
            <div className="w-full lg:w-1/5 lg:px-6 text-xl text-gray-800 leading-normal">
            <h1>TagBar</h1>
            <ul>
            {tags.map(tag => (
                <li key={tag.node.slug}>
                    <Link to={`/tag/${tag.node.id}`}>
                        {tag.node.name}
                    </Link>
                </li>
               ))}
            </ul>
        </div>
        )
    }
}

export default withApollo(Tagbar);

So you see here in the graphql query that i could pass the posts for each tag in the map function to the tag component but im not sure if i should do that...meaning render the tag component inside of tagbar.js...

tagbar is a sidebar on the right side of the ui with the list of tags.

tag.js

import React, { Component } from 'react';
import { withApollo } from 'react-apollo';
import { Link } from 'react-router-dom';
import gql from 'graphql-tag';


const TAG_QUERY = gql`
query TagQuery($filter: ID!) {
    tag(id: $filter) {
      slug
      name
      posts {
        edges {
          node {
            content
            slug
            title
          }
        }
      }
    }
  }
`;  



class Tag extends Component {
    constructor(props){
        super(props);
        this.state = {
            tag: {
                name: "",
                posts: []
            }
        }
    }

    componentDidMount(){
        this.executeTagQuery();
    }

    executeTagQuery = async () => {
        const { match, client } = this.props;
        const filter = match.params.id;
        const result = await client.query({
            query: TAG_QUERY,
            variables: { filter }
        })
        const { name } = result.data.tag;
        let posts = result.data.tag.posts.edges;
        posts = posts.map(post => {
            const finalLink = `/tag/${post.node.id}`;
            const modifiedTag = { ...post };
            modifiedTag.node.link = finalLink;
            return modifiedTag;
        })
        const tag = {
          name,
          posts
        }
        this.setState({ tag });
    }

    render(){
        const { tag } = this.state;
        return (
            <div className="w-full lg:w-3/5 p-8 mt-6 lg:mt-0 text-gray-900 leading-normal bg-white border border-gray-400 border-rounded">
              <h4><strong>Posts with Tag:</strong> <em>{tag.name}</em></h4>
              <ul className="py-10 mx-auto">
                {tag.posts.map(post=> (
                  <li key={post.node.slug} className="">
                      <div className="flex my-10">
                        <div className="bg-white w-3/4 m-auto border-1  border-dashed border-gray-100 shadow-md rounded-lg overflow-hidden">
                            <img src="https://via.placeholder.com/400x200" alt="" className="w-full object-cover object-center" />
                            <div className="p-4">
                                <Link to={post.node.link} className="mx-auto f text-gray-900 font-semibold">{post.node.title}</Link>
                                <br/>
                                <span className="text-gray-700">{post.node.content}</span>
                            </div>
                        </div>
                    </div>   
                  </li>
                ))}
              </ul>
          </div>
        )
    }
}

export default withApollo(Tag);

Discussion

pic
Editor guide
Collapse
highcenburg profile image
Vicente G. Reyes

Hey, community mod here. I highly suggest you use the #help tag to get more traction on this. Cheers!

Collapse
teaglebuilt profile image
dillan teagle Author

haha thats great advice, thank you. I did not realize I left the most relevant tag out!

Collapse
highcenburg profile image
Vicente G. Reyes

haha no worries!