PostWidget component in React

This is the fifth part of Create react app with GraphQL in WordPress

In this part we will develop PostWidget component and a small edit of src/components/AppRouter.js

First small tweek of AppRouter.js

  • First import milligram in AppRouter to use in everywhere.
  • We will use a common component in header area of our application. Create src/components/Header.js
  • Update state to store title
state = {
  title: "",
  posts: []
};
  • Update query to fetch Blog title
client
      .query({
        query: gql`
          {
            generalSettings {
              title
            }
            posts {
              edges {
                node {
                  id
                  title
                  date
                  link
                  content
                  excerpt
                }
              }
            }
          }
        `
      })
      .then(result => {
        this.setState({
          posts: result.data.posts.edges,
          title: result.data.generalSettings.title
        });
      });
  • Add title props in render method of AppRouter.
      <div className="container">
        <BrowserRouter>
          <Header title={this.state.title} />
          <Switch>
            <Route
              exact
              path="/"
              render={props => <App {...props} state={this.state.posts} />}
            />
            <Route
              path="/post/:postID"
              render={props => <Post {...props} state={this.state.posts} />}
            />
            <Route component={NotFound} />
          </Switch>
        </BrowserRouter>
      </div>

So, now AppRouter.js file will

import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import ApolloClient, { gql } from "apollo-boost";
import "milligram";
import Header from "./components/Header";
import App from "./components/App";
import Post from "./components/Post";
import NotFound from "./components/NotFound";

class AppRouter extends React.Component {
  state = {
    title: "",
    posts: []
  };

  componentDidMount() {
    const client = new ApolloClient({
      uri: "http://mrinalbd.com/?graphql"
    });
    client
      .query({
        query: gql`
          {
            generalSettings {
              title
            }
            posts {
              edges {
                node {
                  id
                  title
                  date
                  link
                  content
                  excerpt
                }
              }
            }
          }
        `
      })
      .then(result => {
        this.setState({
          posts: result.data.posts.edges,
          title: result.data.generalSettings.title
        });
      });
  }
  render() {
    return (
      <div className="container">
        <BrowserRouter>
          <Header title={this.state.title} />
          <Switch>
            <Route
              exact
              path="/"
              render={props => <App {...props} state={this.state.posts} />}
            />
            <Route
              path="/post/:postID"
              render={props => <Post {...props} state={this.state.posts} />}
            />
            <Route component={NotFound} />
          </Switch>
        </BrowserRouter>
      </div>
    );
  }
}

export default AppRouter

Develop Header Component
In src/components/Header.js

import React from "react";
import { Link } from "react-router-dom";

class Header extends React.Component {
  render() {
    return (
      <div>
        <Link to="/">
          <h1>{this.props.title}</h1>
        </Link>
      </div>
    );
  }
}
export default Header;

Develop PostWidget
Let’s open src/components/PostWidget.js.
First import { Link } and DomPurify

import { Link } from "react-router-dom";
import DOMPurify from "dompurify";

Then, render the title in link wrapper like this

<div>
  <Link to={`/post/${this.props.post.node.id}`}>
    <p
    dangerouslySetInnerHTML={{
    __html: DOMPurify.sanitize(this.props.post.node.title)
    }}
    />
  </Link>
</div>

So, full code of src/components/PostWidget.js is

import React from "react";
import { Link } from "react-router-dom";
import DOMPurify from "dompurify";

class PostWidget extends React.Component {
  render() {
    return (
      <div>
        <Link to={`/post/${this.props.post.node.id}`}>
          <p
            dangerouslySetInnerHTML={{
              __html: DOMPurify.sanitize(this.props.post.node.title)
            }}
          />
        </Link>
      </div>
    );
  }
}
export default PostWidget;

At last of this our application will be

Posts component in React

This is the fourth part of Create react app with GraphQL in WordPress

In this part, we will develop Posts component lives at src/components/Posts.js

First, we import Link component from react-router-dom and dompurify

import { Link } from "react-router-dom";
import DOMPurify from "dompurify";

In Posts component, first declare excerpt as

excerpt = this.props.post.node.excerpt;

Now, in return we create a link. Link component of react-router-dom creates link.

<Link to={`/post/${this.props.post.node.id}`}>
  <h2
    dangerouslySetInnerHTML={{
      __html: DOMPurify.sanitize(this.props.post.node.title)
    }}
  />
</Link>

Then render excerpt as

<article>
  <p
  dangerouslySetInnerHTML={{
    __html: DOMPurify.sanitize(
       this.excerpt.slice(0, this.excerpt.indexOf("Continue reading"))
    )
  }}
  />
</article>

Finally, src/components/Posts.js full codes are

import React from "react";
import { Link } from "react-router-dom";
import DOMPurify from "dompurify";

class Posts extends React.Component {
  excerpt = this.props.post.node.excerpt;

  render() {
    return (
      <div>
        <Link to={`/post/${this.props.post.node.id}`}>
          <h2
            dangerouslySetInnerHTML={{
              __html: DOMPurify.sanitize(this.props.post.node.title)
            }}
          />
        </Link>
        <article>
          <p
            dangerouslySetInnerHTML={{
              __html: DOMPurify.sanitize(
                this.excerpt.slice(0, this.excerpt.indexOf("Continue reading"))
              )
            }}
          />
        </article>
      </div>
    );
  }
}
export default Posts;

At now, our app is like this

AppRouter setup with React, GraphQL with WordPress

This is the second part of Create react app with GraphQL in WordPress

In this part, we will build src/AppRouter.js.


We will use { BrowserRouter, Route, Switch } from react-router-dom.
We will use ApolloClient and {gql} from apollo-boost package to connect React with Apollo. And import milligram CSS.
We will use App component here. Also, Post and NotFound component import here from respective file.

import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import ApolloClient, { gql } from "apollo-boost";
import "milligram";
import App from './App';
import Post from './components/Post';
import NotFound from './components/NotFound';

We will use react-router-dom’s { BrowserRouter, Route, Switch } components here.

render() {
    return (
      <div className="container">
        <BrowserRouter>
          <Switch>
            <Route
              exact
              path="/"
              render={props => <App {...props} state={this.state.posts} />}
            />
            <Route
              path="/post/:postID"
              render={props => <Post {...props} state={this.state.posts} />}
            />
            <Route component={NotFound} />
          </Switch>
        </BrowserRouter>
      </div>
    );
  }

Here, the mechanism of Switch is like that,

  • When URL is root BrowserRouter render App component.
  • If URL is goes to single post BrowserRouter render Post component. Here :postID placeholder will be changed with real post id. Here, we render Post component with parent props and state.
  • If any user goes to other URL, BrowserRouter render NotFound component.

In AppRouter class, state is defined here. We can store data in state and use this state in different component.

state = {
  posts: []
},

At this point we will use componentDidMount life cycle. This life cycle is hooked when component mounted.

Here, we will use instance of ApolloClient class. ApolloClient class need uri where defined http://mrinalbd.com/?graphql .

componentDidMount() {
  const client = new ApolloClient({
    uri: 'http://mrinalbd.com/?graphql'
  });
}

After defined client, we will run graphql query and then set posts in state. Let’s start dig in mud. Plan for now –
Step 1: ApolloClient’s instance client has query method. In this query we can use gql (graphql) which we imported at the start of this file.
Step 2: If this query successful then run a function. In this function we will write a command to store these data

Second, write the codes.

client
    .query({
      query: gql`
        {
          generalSettings {
              title
            }
          posts {
            edges {
              node {
                id
                title
                date
                link
                content
                excerpt
              }
            }
          }
        }
      `
    })
    .then(result => {
      this.setState({ posts: result.data.posts.edges });
    });

It is long code (for me). So break it down.
First we run a query to fetch data. This query is from official documentation of wpgraphql. https://docs.wpgraphql.com/getting-started/posts.
Second, run the promise of client. In this method we write an array function where result is parameter. This function command to state, let’s update. setState is recommended method to update state. And in this method update posts by post’s data, which we get from previous query.
So, Final code of src/AppRouter.js

import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import ApolloClient, { gql } from "apollo-boost";
import App from "../App";
import Post from "./Post";
import NotFound from "./NotFound";

class AppRouter extends React.Component {
  state = {
    posts: []
  };

  componentDidMount() {
    const client = new ApolloClient({
      uri: "http://mrinalbd.com/?graphql"
    });
    client
      .query({
        query: gql`
          {
            posts {
              edges {
                node {
                  id
                  title
                  date
                  link
                  content
                  excerpt
                }
              }
            }
          }
        `
      })
      .then(result => {
        this.setState({ posts: result.data.posts.edges });
      });
  }
  render() {
    return (
      <BrowserRouter>
        <Switch>
          <Route exact path="/" render={props => <App {...props} state={this.state.posts} />} />
          <Route
            path="/post/:postID"
            render={props => <Post {...props} state={this.state.posts} />}
          />
          <Route component={NotFound} />
        </Switch>
      </BrowserRouter>
    );
  }
}

export default AppRouter;