Twitter-Clone(4~5)

Coaspe·2021년 3월 5일
0

Twitter-Clone

목록 보기
2/4
post-thumbnail

➰Routing in React

1. Using react-router-dom

Operate npm install react-router-dom

2. 🔨 Modify 📁web ➡ 📁src ➡ 📃App.tsx

import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';
import Users from './components/Users';
import {BrowserRouter as Router, Route, Switch} from 'react-router-dom';
import Landing from './components/Landing';

const client = new ApolloClient({
  uri:"http://localhost:4000",
  cache: new InMemoryCache()
})

function App() {
  return (
    <ApolloProvider client={client}>
      1️⃣ <Router>
        <Switch>
          <Route path="/landing">
            <Landing />
          </Route>
          <Route path="/">
            <Users />
          </Route>
        </Switch>
      </Router>
    </ApolloProvider>
  );
}

export default App;

📋Memo(App.tsx)

1️⃣ <Router>
  1. Using `BrowserRouter` made `Router` that routes to "/" and "/landing"

📝Create 📁web ➡ 📁src ➡ 📁components ➡ 📃Landing.tsx

import React from "react";

const Landing = () => {
    return(
        <div>
            <h1>Landing</h1>
        </div>
    );
}

export default Landing;

➰Authentication

To create context that gets token and passes it along for each request

2. 🔨 Modify 📁web ➡ 📁src ➡ 📃App.tsx

import { ApolloClient, InMemoryCache, ApolloProvider, HttpLink } from '@apollo/client';
import Users from './components/Users';
import {BrowserRouter as Router, Route, Switch} from 'react-router-dom';
import Landing from './components/Landing';
import {setContext} from 'apollo-link-context';
import Signup from './pages/Signup';
import Login from './pages/Login';

// const client = new ApolloClient({
//   uri:"http://localhost:4000",
//   cache: new InMemoryCache()
// })

🚗 const httpLink = new HttpLink({uri:'http://localhost:4000'})
🚓 const authlink = setContext( async( req, { headers } ) => { // {headers : previous context}
// setContext((GraphQL request being executed, previous context) => {return object or a promise => returns an object to set the new context of a request})
// context is an object shared by all the resolvers of a specific execution. 
// It's useful for keeping data such as authentication info, the current user, database connection, data sources and other things you need for running your business logic.
  const token = localStorage.getItem('token')

  return {
    ...headers,
    headers:{
      Authorization: token ? `Bearer ${token}` : null
    }
  }
})

const link = authlink.concat(httpLink as any)
// By default, Apollo Client uses Apollo Link's HttpLink to send GraphQL queries over HTTP.
// One of uri or link is required. If you provide both, link takes precedence.
const client = new ApolloClient(
 {
  🚕 link: (link as any),
  cache: new InMemoryCache()}
)
function App() {
  return (
    <ApolloProvider client={client}>
      <Router>
        <Switch>
          <Route path="/landing">
            <Landing />
          </Route>
          <Route path="/signup">
            <Signup />
          </Route>
            <Route path="/login">
            <Login />
          </Route>        
          <Route path="/">
            <Users />
          </Route>
        </Switch>
      </Router>
    </ApolloProvider>
  );
}

export default App;


In the case of my code, I have one ApolloLink and one Terminating Link
1. ApolloLink might add an HTTP header to the outgoing operation request for authentication purposes.
2. Terminating Link sends the operation to its destination (usually a GraphQL server over HTTP).

🔰 What is Context?

  1. In Apollo Context is an object shared by all the resolvers of a specific execution.
    It's useful for keeping data such as authentication info, the current user, database connection, data sources and other things you need for running your business logic.
  2. In Network Context may include network addresses, packets, fingerprints, or other types of data

📋Memo(App.tsx)

🚗 const httpLink = new HttpLink({uri:'http://localhost:4000'})
1.HttpLink is a termainating link that sensd a GraphQL operation to a remote endpoint over HTTP.
2.Apollo Client uses HttpLink by default when you provide the uri option to the ApolloClient constructor.

🚓 const authlink = setContext( async( req, { headers } ) (Context Setter)
1.setContext((GraphQL request being executed, previous context) =>
{return object or a promise => returns an object to set the new context of a request})

🚕 link: (link as any)
1. By default, Apollo Client uses Apollo Link's HttpLink to send GraphQL queries over HTTP.
2. One of uri or link is required. If you provide both, link takes precedence.

3. 📝Create 📁web ➡ 📁src ➡ 📁pages ➡ 📃Signup.tsx

import {gql, useMutation} from '@apollo/client'
🚗 import {ErrorMessage, Field, Form, Formik} from 'formik';
🚓 import * as Yup from 'yup'
import {useHistory} from 'react-router-dom';
//npm install formik yup
//npm install -D types/yup

const SIGNUP_MUTATION = gql`
    mutation signup($name: String, $email: String!, $password: String!){
        signup(name: $name, email: $email, password: $password) {
            token
        }
    }
`
interface SignupValues{
    email: string
    password: string
    confirmPassword: string
    name: string
}

const Signup = () => {
    const history = useHistory();
    const [signup, { data }] = useMutation(SIGNUP_MUTATION);

    const initialValues: SignupValues= {
        email:'',
        password:'',
        confirmPassword:'',
        name:''
    }
    🚕 const validationSchema = Yup.object({
        email: Yup.string()
            .email("Invalid email address")
            .required("Email Required"),
        password: Yup.string()
            .max(20, "Must be 20 charactres or less")
            .required("Password Required"),
        confirmPassword: Yup.string()
            .oneOf([Yup.ref("password")], "Passwords must match"),
        name: Yup.string()
            .max(15, "Must be 15 characters or less")
            .required("Name Required")
    })
    return(
        <div>
            <h1>Signup</h1>
            <Formik
            initialValues={initialValues}
            validationSchema={validationSchema}
            🛺 onSubmit={async( value, {setSubmitting}) => {
                setSubmitting(true)
                const response = await signup({
                    variables: value
                })
                localStorage.setItem("token", response.data.signup.token)
                setSubmitting(false)
                history.push('/users')
            }}
            >
                <Form>
                    <Field name="email" type="text" placeholder="Email" />
                    <ErrorMessage name="email" component={'div'} />
                    <Field name="name" type="text" placeholder="Name" />
                    <ErrorMessage name="name" component={'div'} />
                    <Field name="password" type="text" placeholder="Password" />
                    <ErrorMessage name="password" component={'div'} />                    
                    <Field name="confirmPassword" type="text" placeholder="Confirm Password" />
                    <ErrorMessage name="confirmPassword" component={'div'} />
                    <button type="submit" >Signup</button>
                </Form>

            </Formik>
        </div>
    );
}

export default Signup;

📋Memo(App.tsx)

🚗 About Formik

🚓 About Yup
1. Yup is a Javascript schema builder for value parsing and validation.

🚕 onSubmit={async( values, { setSubmitting }) =>{...})
1. values are values that are submitted from <Form> tag

4. 📝Create 📁web ➡ 📁src ➡ 📁pages ➡ 📃Login.tsx

import {gql, useMutation} from '@apollo/client'
import {ErrorMessage, Field, Form, Formik} from 'formik';
import * as Yup from 'yup'
import {useHistory} from 'react-router-dom';

const LOGIN_MUTATION = gql`
    mutation login($email: String!, $password: String!){
        login(email: $email, password: $password) {
            token
        }
    }
`
interface LoginValues{
    email: string
    password: string
}

const Login = () => {
    const history = useHistory();
    const [login, { data }] = useMutation(LOGIN_MUTATION);

    const initialValues: LoginValues= {
        email:'',
        password: ''
    }
    const validationSchema = Yup.object({
        email: Yup.string()
            .email("Invalid email address")
            .required("Email Required"),
        password: Yup.string()
            .max(20, "Must be 20 charactres or less")
            .required("Password Required")
    })
    return(
        <div>
            <h1>Login</h1>
            <Formik
                initialValues={initialValues}
                validationSchema={validationSchema}
                onSubmit={async (value, { setSubmitting }) => {
                    setSubmitting(true)
                    const response = await login({
                        variables: value
                    })
                    localStorage.setItem("token", response.data.login.token)
                    setSubmitting(false)
                    history.push('/users')
                }}
            >
                <Form>
                    <;Field name="email" type="text" placeholder="Email" />
                    <ErrorMessage name="email" component={'div'} />

                    <Field name="password" type="password" placeholder="Password" />
                    <ErrorMessage name="password" component={'div'} />  
                    
                    <button type="submit" >Login</button>
                </Form>

            </Formik>
        </div>
    );
}

export default Login;
profile
https://github.com/Coaspe

0개의 댓글