DEV Community

loading...
Cover image for [ PART 14 ] Creating a Twitter clone with GraphQL, Typescript, and React ( starting the Frontend )

[ PART 14 ] Creating a Twitter clone with GraphQL, Typescript, and React ( starting the Frontend )

ipscodingchallenge profile image ips-coding-challenge ・3 min read

Hi everyone ;).

As a reminder, I'm doing this Tweeter challenge

Github repository

Db diagram

A little bit of Frontend

For the Frontend part, I will use React + Tailwindcss + Typescript. I just found a template so let's try it. If I can win some time avoiding to configure everything... I'll take it ^^. For the design , every challenge on devChallenges.io provides a Figma file so I don't have to start the design from scratch. You can thanks

nghiemthu image
:D
npx create-react-app challenge_twitter_front --template tailwindcss-typescript
Enter fullscreen mode Exit fullscreen mode
yarn start
Enter fullscreen mode Exit fullscreen mode

Everything seems to work. Let's add more libraries that I will need.

yarn add @apollo/client graphql recoil react-hook-form @hookform/resolvers yup react-router-dom date-fns react-icons
Enter fullscreen mode Exit fullscreen mode
  • @apollo/client and graphql : for our queries/mutation & graphql related stuff
  • recoil: for our global state management
  • react-hook-form @hookform/resolvers yup: for our form validation
  • react-router-dom: The router
  • date-fns: we'll have some date to format
  • react-icons: To have some icons to play with ;)

To start, let's just add the Router with some pages:

src/App.tsx

import React from 'react'
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'
import Home from './pages/Home'
import Login from './pages/Login'
import Register from './pages/Register'

function App() {
  return (
    <Router>
      <Switch>
        <Route exact path="/login">
          <Login />
        </Route>
        <Route exact path="/register">
          <Register />
        </Route>
        <Route exact path="/">
          <Home />
        </Route>
      </Switch>
    </Router>
  )
}

export default App

Enter fullscreen mode Exit fullscreen mode

And as an example, here is my Register page:

src/pages/Register.tsx

import React from 'react'

const Register = () => {
  return <div>Register</div>
}

export default Register
Enter fullscreen mode Exit fullscreen mode

Register a user

We will start with the authentication. We will use react-hooker-form with yup for the validation. But before working on the Register page, let's create our apolloClient.

src/client/index.ts

import { ApolloClient, InMemoryCache } from '@apollo/client'

const client = new ApolloClient({
  uri: process.env.REACT_APP_BACKEND_URL || 'http://localhost:4000',
  cache: new InMemoryCache(),
})

export default client

Enter fullscreen mode Exit fullscreen mode

For now, I just follow the documentation ;). To have access to some hooks provided by the apolloClient, we will wrap our App with the ApolloProvider

src/index.tsx

import { ApolloProvider } from '@apollo/client'
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import client from './client'
import './styles/index.css'

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

Enter fullscreen mode Exit fullscreen mode

Just for the sake of testing if everything works as expected I will play in my Register page ;).

src/pages/Register.ts

import { gql, useMutation } from '@apollo/client'
import React from 'react'

const REGISTER = gql`
  mutation($input: RegisterPayload!) {
    register(input: $input) {
      token
      user {
        id
        username
        display_name
        email
        created_at
        updated_at
      }
    }
  }
`

const Register = () => {
  const [register, { loading, data, error }] = useMutation(REGISTER)

  return (
    <div>
      <button
        onClick={() => {
          register({
            variables: {
              input: {
                username: 'new',
                email: 'new@test.fr',
                display_name: 'New',
                password: 'password',
              },
            },
          })
        }}
      >
        Register
      </button>
      {loading && <div>Loading...</div>}
      {data && <div>{data.register.user.username}</div>}
    </div>
  )
}

export default Register

Enter fullscreen mode Exit fullscreen mode

Don't forget to start the server and let's give a try ;).

Register Page with result in console

Nice ;). The client seems to work as expected.

I will stop here for now and I will start to really work on the user's registration in the next part ;).

Ciao & Take care ;).

Discussion (0)

Forem Open with the Forem app