Generator
함수에 * 별을 다니깐 함수 호출이 바로 실행이 안됨
gen{<suspended>} 안에 있는 next 라는 함수를 붙여야 다음 코드로 진행된다.
gen().next()
왜 1밖에 안찍히지? - > generator 사용 이유
함수 안의 코드들을 내가 구분해서 사용할 수 있음 next를 써야지만 안의 코드 명령들을 이어서 쓸 수 있음
gen 이라는 함수를 어떤 특정 변수에는 담아놔야함 **
함수에 return 이 없는데 무언가가 return 됨
{value:undefined, done:false}
generator 함수 특성 : yield 가 return 이랑 비슷하다고 생각해보기
next() 할 때마다 yield 가 return 해주는구나~
yield 3 이라고 쓰면 value에 들어감
done의 뜻 : 마무리가 되었는가 false : 아직 안끝났다. true :끝났다. 더이상 실행할 것이 없다.
Generator 에서는 무한 반복이 가능함
** 특징 : 무한반복 가능 / 변수에 담아서 사용해야 한다.
https://ko.javascript.info/generators
Middleware
redux-thunk & redux-saga 모두 redux의 미들웨어
Redux middleware의 역할
reducer 라는 값이 상태값 변화게 해주는 아이
dispatch ----> reducer에 가서 처리되지 전 먼저 들렸다 가는 곳이 middleware
DISPATCH ----------> MIDDLEWARE ----------> REDUCER -------- (middleware 가능) -------> STATE
middleware에서는 비동기 처리 / 다양한 상태 처리 / DB와의 체크 등등... ----> 그리고 reducer 에 보냄
Middleware Thunk 개념만 알고 넘어가기 ! (이걸로 만들 건 아니여)
1) configureStore.js
import {createWrapper} from 'next-redux-wrapper'
import {applyMiddleware, compose, createStore} from 'redux'
import reducer from '../reducers' //index 생략 가능
import {composeWithDevTools} from 'redux-devtools-extension'
const loggerMiddleware = ({dispatch,getState}) =>(next)=>(action)=>{
console.log('action=',action)
console.log('dispatch=', dispatch)
console.log('getState=', getState)
return next(action)
}
const configureStore=()=>{
const middlewares = [loggerMiddleware]
const enhancer = process.env.NODE_ENV === 'production'
? compose(applyMiddleware(...middlewares))
: composeWithDevTools(applyMiddleware(...middlewares))
const Store = createStore(reducer, enhancer)
return Store
}
// Store 자체를 가지는게 아닌 Store를 return해 주는 함수를 담아야함
const wrapper = createWrapper(configureStore,{
debug:process.env.NODE_ENV === 'development'
//debug:true (개발모드이므로) 와 같은 의미
})
export default wrapper
createStore(reducer, enhancer) -> enhancer 를 미리 만들어 놓음
console.log
action 값은 object 근데 항상 object로 떨어지는게 아니고 우리가 그렇게 만들기 때문
action 값을 객체로 할 것인지 함수로 할 것인지 구분
login -> db 확인 (middleware) -> dispatch -> reducer -> state change -> rerendering
Thunk 사용 해보기
1. thunk 다운
npm i redux-thunk
2. 가져오기, middlewares 배열에 넣기
configureStore.js
import thunkMiddleware from 'redux-thunk' //가져오기
const loggerMiddleware = ({dispatch,getState}) =>(next)=>(action)=>{
console.log('action=',action)
console.log('dispatch=', dispatch)
console.log('getState=', getState)
return next(action)
}
const configureStore=()=>{
const middlewares = [loggerMiddleware,thunkMiddleware] //추가
3. login.jsx 수정
import FormLayout from "../components/FormLayout"
import Head from 'next/head'
import Router from 'next/router'
import userInput from '../hooks/userInput'
// redux
import {useDispatch} from 'react-redux'
import {UserLoginAction} from '../reducers/user' //가져오기
const Login = () => {
const dispatch = useDispatch()
const userid = userInput('') // object
const userpw = userInput('') // object
const handleSubmit=(e)=>{
e.preventDefault()
//dispatch(UserLoginAction()) // 요렇게 수정
//dispatch 안에 넣는게 action -> 여기에 함수 넣기 (thunk)
dispatch(()=>{
return(dispatch)=>{
setTimeout(()=>{
dispatch(UserLoginAction())
},1000)
}
})
.
.
.
4. reducers > user.js
상태값에 loadding:false 추가, User_login_request, success, error 추가
const initialState = {
IsLogin: false,
loadding:false,
}
const USER_LOGIN = "USER_LOGIN" // 오타 났을 때 대비
const USER_LOGOUT = "USER_LOGOUT"
const USER_LOGIN_REQUEST = "USER_LOGIN_REQUEST"
const USER_LOGIN_SUCCESS = "USER_LOGIN_SUCCESS"
const USER_LOGIN_ERROR = "USER_LOGIN_ERROR"
export const UserLoginAction = () => {
return {
type: USER_LOGIN
}
}
export const UserLogin_REQUEST =()=>{
return {
type:USER_LOGIN_REQUEST,
data
}
}
export const UserLogin_SUCCESS=()=>{
return{
type:USER_LOGIN_SUCCESS
}
}
export const UserLogin_ERROR=()=>{
return{
type:USER_LOGIN_ERROR
}
}
export const UserLogoutAction = () => {
return {
type: USER_LOGOUT
}
}
const reducer = (state = initialState, action) => {
switch (action.type) {
case USER_LOGIN:
console.log('로그인 신호왓다')
return {
...state,
IsLogin: true
}
case USER_LOGOUT:
console.log('로그아웃 신호왓다리')
return {
...state,
IsLogin: false
}
default:
return state
}
}
export default reducer
↓↓
const initialState = {
IsLogin: false,
loadding:false,
}
//const USER_LOGIN = "USER_LOGIN" // 오타 났을 때 대비
const USER_LOGOUT = "USER_LOGOUT"
const USER_LOGIN_REQUEST = "USER_LOGIN_REQUEST"
const USER_LOGIN_SUCCESS = "USER_LOGIN_SUCCESS"
const USER_LOGIN_ERROR = "USER_LOGIN_ERROR"
//UserLoginAction 은 middleware thunk 로 인해 사용할 수 있는 것
// 얘가 실행이 됨
// login.js -> handleSubmit눌렀을 때 실행됨(dispatch) ->
// user.js -> 아래 코드 실행됨
export const UserLoginAction = (data) => {
return async (dispatch)=>{
dispatch(UserLogin_REQUEST())
try{ // fetch or axios 성공 fetch:내장 axios : 코드가져와야함
const response = await fetch('http://localhost:3000/api/login',{
method:'POST',
headers:{
"Content-type":"application/json",
},
// body 내용은 객체이면 안된다 !
body:JSON.stringify({...date})
})
const result = await response.json()
dispatch(UserLogin_SUCCESS(result))
}catch(e){ // 실패
dispatch(UserLogin_ERROR())
}
}
}
export const UserLogin_REQUEST =(data)=>{
return {
type:USER_LOGIN_REQUEST,
data
}
}
export const UserLogin_SUCCESS=()=>{
return{
type:USER_LOGIN_SUCCESS
}
}
export const UserLogin_ERROR=()=>{
return{
type:USER_LOGIN_ERROR
}
}
export const UserLogoutAction = () => {
return {
type: USER_LOGOUT
}
}
const reducer = (state = initialState, action) => {
switch (action.type) {
case USER_LOGIN_REQUEST:
return{
...state,
}
case USER_LOGIN_SUCCESS:
return{
...state,
IsLogin:true
}
case USER_LOGIN_ERROR:
return{
...state,
}
// case USER_LOGIN:
// console.log('로그인 신호왓다')
// return {
// ...state,
// IsLogin: true
// }
case USER_LOGOUT:
console.log('로그아웃 ')
return {
...state,
IsLogin: false
}
default:
return state
}
}
export default reducer
login.jsx handleSubmit 에 async e , await dispatch 달아주기
-> 로그인 요청이 끝나야 page가 넘어감 -> async, await 붙여서 UserLoginAction() 안의 try , catch 의 실행이 끝날때까지 기다렸다가 page가 넘어가게됨 (안적어주면 페이지 이동이 먼저 일어남)
const handleSubmit= async (e)=>{
e.preventDefault()
//dispatch(UserLoginAction()) // 요렇게 수정
//dispatch 안에 넣는게 action -> 여기에 함수 넣기 (thunk)
await dispatch(UserLoginAction())
userid.value==="asdf" && userpw.value==="asdf"
? Router.push('/') : alert('id 또는 pw가 다릅니다.')
}
백엔드 만들기
0. blog > back 폴더까지 터미널 경로 들어오기
1. 간단한 server 만들기위한 packages 설치
npm init
npm i express body-parser cors
2. back > server.js 기본 파일 생성 및 코드 작성
const express = require('express')
const app = express()
const bodyParser = require('body-parser')
const cors = require('cors')
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended:false}))
app.use(cors())
app.get('/', (req,res)=>{
res.send('helllo')
})
app.listen(3000,()=>{
console.log('start port : 3000')
})
helloo뜨는지 확인
3. front에서 요청한 localhost:3000/api/login method:post 만들기
app.post('/api/login',(req,res)=>{
console.log(req.body.userid, req.body.userpw)
res.json({
userid:'asdf',
userpw:'asdf',
})
})
userid, userpw 의 문제가 있음 확인해보기
login.jsx 에 매개변수가 비어있었음 ! data 만들어서 넣어주기
const handleSubmit= async (e)=>{
e.preventDefault()
const data ={
userid:userid.value,
userpw:userpw.value
}
//dispatch(UserLoginAction()) // 요렇게 수정
//dispatch 안에 넣는게 action -> 여기에 함수 넣기 (thunk)
await dispatch(UserLoginAction(data))
userid.value==="asdf" && userpw.value==="asdf"
? Router.push('/') : alert('id 또는 pw가 다릅니다.')
}
=> 결과
로그인 됨
흐름 : login - handleSubimt -> dispatch(UserLoginAction() 실행 ->
user.js - retrun - dispatch(UserLogin_REQUEST) 실행 -> try(UserLogin_SUCCESS) or catch (UserLogin_ERROR) 실행
server.js 수정
app.post('/api/login',(req,res)=>{
const {userid,userpw} = req.body;
console.log(userid,userpw)
//원래는 DB에서 조회해서 결과 던져주기!
let result={};
if(userid=="asdf" && userpw =='asdf'){
result={
result:'ok',
msg:'로그인에 성공했습니다.'
}
}else{
result={
result:'fail',
msg:'아이디와 패스워드가 틀립니다. '
}
}
res.json(result)
})
login.js 주석처리
user.js 수정
export const UserLoginAction = (data) => {
return async (dispatch)=>{
dispatch(UserLogin_REQUEST())
console.log(data, 'data')
try{ // fetch or axios 성공 fetch:내장 axios : 코드가져와야함
const response = await fetch('http://localhost:3000/api/login',{
method:'POST',
headers:{
"Content-type":"application/json",
},
// body 내용은 객체이면 안된다 !
body:JSON.stringify({...data})
})
const result = await response.json()
result.result=='ok' ?
dispatch(UserLogin_SUCCESS(result))
: dispatch(UserLogin_ERROR())
}catch(e){ // 실패
dispatch(UserLogin_ERROR())
}
}
}
login.jsx에서 상태값을 가져오기위해 useSelector 가져오기
// redux
import {useDispatch, useSelector} from 'react-redux'
user.js 에loadding ㅇ추가
const initialState = {
IsLogin: false,
loadding:false,
}
//const USER_LOGIN = "USER_LOGIN" // 오타 났을 때 대비
const USER_LOGOUT = "USER_LOGOUT"
const USER_LOGIN_REQUEST = "USER_LOGIN_REQUEST"
const USER_LOGIN_SUCCESS = "USER_LOGIN_SUCCESS"
const USER_LOGIN_ERROR = "USER_LOGIN_ERROR"
//UserLoginAction 은 middleware thunk 로 인해 사용할 수 있는 것
// 얘가 실행이 됨
// login.js -> handleSubmit눌렀을 때 실행됨(dispatch) ->
// user.js -> 아래 코드 실행됨
export const UserLoginAction = (data) => {
return async (dispatch)=>{
dispatch(UserLogin_REQUEST())
console.log(data, 'data')
try{ // fetch or axios 성공 fetch:내장 axios : 코드가져와야함
const response = await fetch('http://localhost:3000/api/login',{
method:'POST',
headers:{
"Content-type":"application/json",
},
// body 내용은 객체이면 안된다 !
body:JSON.stringify({...data})
})
const result = await response.json()
result.result=='ok' ?
dispatch(UserLogin_SUCCESS(result))
: dispatch(UserLogin_ERROR())
}catch(e){ // 실패
dispatch(UserLogin_ERROR())
}
}
}
export const UserLogin_REQUEST =(data)=>{
return {
type:USER_LOGIN_REQUEST,
loadding:true,
}
}
export const UserLogin_SUCCESS=()=>{
return{
type:USER_LOGIN_SUCCESS,
loadding:false,
}
}
export const UserLogin_ERROR=()=>{
return{
type:USER_LOGIN_ERROR,
loadding:false,
}
}
export const UserLogoutAction = () => {
return {
type: USER_LOGOUT
}
}
const reducer = (state = initialState, action) => {
switch (action.type) {
case USER_LOGIN_REQUEST:
return{
...state,
}
case USER_LOGIN_SUCCESS:
return{
...state,
IsLogin:true
}
case USER_LOGIN_ERROR:
return{
...state,
}
// case USER_LOGIN:
// console.log('로그인 신호왓다')
// return {
// ...state,
// IsLogin: true
// }
case USER_LOGOUT:
console.log('로그아웃 ')
return {
...state,
IsLogin: false
}
default:
return state
}
}
export default reducer
login.jsx
'블록체인 기반 핀테크 및 응용 SW개발자 양성과정 일기' 카테고리의 다른 글
[100일차] Next 배포 방법 / https 도메인 연결 (0) | 2021.08.05 |
---|---|
[91-110일차] 어플 개발 with React Native Expo <Before you die > (0) | 2021.08.04 |
[98일차] 20210729 Redux 리덕스 사용법 / reducer 파일 쪼개기 / combine (0) | 2021.07.30 |
[95-97일차 복습] 리액트 (+NEXT) 웹 홈페이지 만들기 기초 (레이아웃 / 로그인 / 회원가입) (0) | 2021.07.29 |
[97일차]20210728 React 리액트 회원가입 로그인 / 리덕스 설치 (0) | 2021.07.28 |