DEV Community

Cover image for Wordpress with React and Apollo
dillan teagle
dillan teagle

Posted on • Updated on

Wordpress with React and Apollo

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')
);
Enter fullscreen mode Exit fullscreen mode

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>
);
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

Discussion (3)

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!