Skip to content
Home » 리 액트 회원 가입 | 13 회원가입 구현 Axios Post 이용한 가입 데이터 전송 빠른 답변

리 액트 회원 가입 | 13 회원가입 구현 Axios Post 이용한 가입 데이터 전송 빠른 답변

당신은 주제를 찾고 있습니까 “리 액트 회원 가입 – 13 회원가입 구현 axios post 이용한 가입 데이터 전송“? 다음 카테고리의 웹사이트 https://kk.taphoamini.com 에서 귀하의 모든 질문에 답변해 드립니다: https://kk.taphoamini.com/wiki/. 바로 아래에서 답을 찾을 수 있습니다. 작성자 \b피클, The 피어클래스 이(가) 작성한 기사에는 조회수 988회 및 좋아요 12개 개의 좋아요가 있습니다.

Table of Contents

리 액트 회원 가입 주제에 대한 동영상 보기

여기에서 이 주제에 대한 비디오를 시청하십시오. 주의 깊게 살펴보고 읽고 있는 내용에 대한 피드백을 제공하세요!

d여기에서 13 회원가입 구현 axios post 이용한 가입 데이터 전송 – 리 액트 회원 가입 주제에 대한 세부정보를 참조하세요

리 액트 회원 가입 주제에 대한 자세한 내용은 여기를 참조하세요.

5-6. 회원인증 폼 (Form) 구성하기 · GitBook

이번 섹션에서는, 인풋과 버튼으로 구성된 로그인폼과 회원가입폼을 만들어보겠습니다. 그러기 위해선, 라벨과 세트로 있는 인풋 컴포넌트와, 로그인 버튼을 만들어 …

+ 여기에 더 보기

Source: backend-intro.vlpt.us

Date Published: 6/5/2021

View: 4287

2021.09.17 React 로그인, 회원가입(1) – 코린이의 정리노트

2021.09.17 React 로그인, 회원가입(1)_정리노트 … 오늘은 프로젝트 세팅에 이어서 로그인, 회원가입 UI 를 만들고 리덕스를 이용해 상태관리 …

+ 여기에 표시

Source: korinkorin.tistory.com

Date Published: 10/18/2021

View: 5400

[리액트/노드 기초] 로그인 시스템 만들기 (8) – 회원가입 페이지 …

이번 글에서는 회원가입 페이지와 로그아웃 기능을 만들어 보겠습니다. 회원가입 페이지 만들기. 회원가입 페이지의 레이아웃은 기본적으로. 로그인 …

+ 자세한 내용은 여기를 클릭하십시오

Source: joonganglib.tistory.com

Date Published: 7/12/2021

View: 3422

React로 블로그 만들기 26. 회원가입 구현하기

먼저 회원가입 컴포넌트 생성 후 라우터를 설정해보겠습니다. … src/page/signup.js */ import React, { Component } from ‘react’; import ‘.

+ 여기에 표시

Source: blog.naver.com

Date Published: 11/21/2022

View: 1186

React | 회원가입 기능 구현하기 – 일상 속 개발록 – 티스토리

유효성 로직을 포함한 회원가입을 진행해보고자 한다. Step.1 : state 설정. 최상위 컴포넌트의 state/fetch 함수 부분 (중요 부분만 발췌)

+ 여기를 클릭

Source: dev-bomdong.tistory.com

Date Published: 1/5/2022

View: 1857

[React] 회원가입 폼 validation 디자인 구현하기 – ChanBLOG

React – 회원가입 폼 valation 디자인 구현하기. 목적 : 핸들러를 구현하여 회원가입 양식에 어긋나는 입력을 할 시, UI에서 텍스트 필드가 오류 색상으로 변경되는 …

+ 더 읽기

Source: chanhuiseok.github.io

Date Published: 6/9/2022

View: 2789

[React] 회원가입 기능 구현 (MySQL / bcrypt / 쿠키)

[React] 회원가입 기능 구현 (MySQL / bcrypt / 쿠키) · 1. MySQL 데이터베이스에 table 생성 · 2. 서버 구현. 1) join 경로 post 요청시. customer_members …

+ 자세한 내용은 여기를 클릭하십시오

Source: 7ingout.tistory.com

Date Published: 8/15/2022

View: 5805

[2주 프로젝트] 로그인/회원가입 기능 – Medium

이용만 했지, 정말 이렇게 로직이 복잡할 줄 몰랐던 로그인/회원가입 기능… … { BrowserRouter as Router, Route, Link } from “react-router-dom”;

+ 더 읽기

Source: medium.com

Date Published: 5/28/2021

View: 4143

주제와 관련된 이미지 리 액트 회원 가입

주제와 관련된 더 많은 사진을 참조하십시오 13 회원가입 구현 axios post 이용한 가입 데이터 전송. 댓글에서 더 많은 관련 이미지를 보거나 필요한 경우 더 많은 관련 기사를 볼 수 있습니다.

13 회원가입 구현   axios post 이용한 가입 데이터 전송
13 회원가입 구현 axios post 이용한 가입 데이터 전송

주제에 대한 기사 평가 리 액트 회원 가입

  • Author: \b피클, The 피어클래스
  • Views: 조회수 988회
  • Likes: 좋아요 12개
  • Date Published: 2022. 5. 8.
  • Video Url link: https://www.youtube.com/watch?v=4aGjSoO5TDY

5-6. 회원인증 폼 (Form) 구성하기 · GitBook

5-6. 회원인증 폼 (Form) 구성하기

이번 섹션에서는, 인풋과 버튼으로 구성된 로그인폼과 회원가입폼을 만들어보겠습니다.

그러기 위해선, 라벨과 세트로 있는 인풋 컴포넌트와, 로그인 버튼을 만들어주어야합니다. 추가적으로 회원가입 페이지로 이동하기 위한 텍스트링크 컴포넌트도 만들어보겠습니다.

InputWithLabel 컴포넌트 만들기

라벨과 함께있는 인풋이니, InputWithLabel 이라는 이름을 설정해주도록 하겠습니다.

src/components/Auth/InputWithLabel.js

import React from ‘react’ ; import styled from ‘styled-components’ ; import oc from ‘open-color’ ; const Wrapper = styled.div ` & + & { margin-top: 1rem; } ` ; const Label = styled.div ` font-size: 1rem; color: ${oc.gray[6]} ; margin-bottom: 0.25rem; ` ; const Input = styled.input ` width: 100%; border: 1px solid ${oc.gray[3]} ; outline: none; border-radius: 0px; line-height: 2.5rem; font-size: 1.2rem; padding-left: 0.5rem; padding-right: 0.5rem; ` ; const InputWithLabel = ({label, …rest}) => ( < Wrapper > < Label > {label} < Input { ...rest }/> ); export default InputWithLabel;

이제 이 컴포넌트를 인덱스에 추가해줍시다.

src/components/Auth/index.js

export { default as AuthWrapper } from ‘./AuthWrapper’ ; export { default as AuthContent } from ‘./AuthContent’ ; export { default as InputWithLabel } from ‘./InputWithLabel’ ;

자, 그럼 이 컴포넌트를 로그인 라우트에서 띄워볼까요? 이메일과 비밀번호 인풋을 넣어줍시다

src/containers/Auth/Login.js

import React, { Component } from ‘react’ ; import { AuthContent, InputWithLabel } from ‘components/Auth’ ; class Login extends Component { render() { return ( ); } } export default Login;

우리가 방금 만든 인풋이 잘 나타났나요?

버튼 만들기

이제 로그인 버튼을 만들어주겠습니다. 버튼의 이름은 AuthButton 으로 하도록 하겠습니다. 컴포넌트의 이름을 지어줄 때는 고유성을 유지해주는것이 좋습니다. 이 부분은 필수사항은 아니지만, 각 컴포넌트마다 고유적인 이름을 설정해주면, 나중에 컴포넌트의 갯수가 많아졌을 때 컴포넌트를 수정해야 할 때 헤멜필요가 없고 IDE의 기능을 사용하여 바로 파일이름을 입력하여 찾을 수 있기 때문입니다.

src/components/Auth/AuthButton.js

import React from ‘react’ ; import styled from ‘styled-components’ ; import oc from ‘open-color’ ; import { shadow } from ‘lib/styleUtils’ ; const Wrapper = styled.div ` margin-top: 1rem; padding-top: 0.6rem; padding-bottom: 0.5rem; background: ${oc.teal[6]} ; color: white; text-align: center; font-size: 1.25rem; font-weight: 500; cursor: pointer; user-select: none; transition: .2s all; &:hover { background: ${oc.teal[5]} ; ${shadow(0)} } &:active { background: ${oc.teal[7]} ; } ` ; const AuthButton = ({children, onClick}) => ( < Wrapper onClick = {onClick} > {children} ); export default AuthButton;

그 다음엔 이 컴포넌트를 컴포넌트 인덱스에 추가하세요.

src/components/Auth/index.js

export { default as AuthWrapper } from ‘./AuthWrapper’ ; export { default as AuthContent } from ‘./AuthContent’ ; export { default as InputWithLabel } from ‘./InputWithLabel’ ; export { default as AuthButton } from ‘./AuthButton’ ;

이제 이 버튼을 인풋들 하단에 렌더링 하세요.

src/containers/Auth/Login.js

import React, { Component } from ‘react’ ; import { AuthContent, InputWithLabel, AuthButton } from ‘components/Auth’ ; class Login extends Component { render() { return ( 로그인 ); } } export default Login;

버튼이 성공적으로 만들어졌습니다!

RightAlignedLink 컴포넌트 만들기

이제 우측에 정렬된 링크 컴포넌트를 만들겠습니다. 이름은 속성을 그대로 RightAlignedLink 라고 짓도록 하죠.

src/components/Auth/RightAlignedLink.js

import React from ‘react’ ; import styled from ‘styled-components’ ; import oc from ‘open-color’ ; import { Link } from ‘react-router-dom’ ; const Aligner = styled.div ` margin-top: 1rem; text-align: right; ` ; const StyledLink = styled(Link) ` color: ${oc.gray[6]} ; &:hover { color: ${oc.gray[7]} ; } ` const RightAlignedLink = ({to, children}) => ( < Aligner > < StyledLink to = {to} > {children} ); export default RightAlignedLink;

컴포넌트를 만들었으니, 인덱스에 추가해줍시다.

src/components/Auth/index.js

export { default as AuthWrapper } from ‘./AuthWrapper’ ; export { default as AuthContent } from ‘./AuthContent’ ; export { default as InputWithLabel } from ‘./InputWithLabel’ ; export { default as AuthButton } from ‘./AuthButton’ ; export { default as RightAlignedLink } from ‘./RightAlignedLink’ ;

이제 이 컴포넌트를 Login 컴포넌트에서 보여줍시다!

src/containers/Auth/Login.js

import React, { Component } from ‘react’ ; import { AuthContent, InputWithLabel, AuthButton, RightAlignedLink } from ‘components/Auth’ ; class Login extends Component { render() { return ( 로그인 회원가입 ); } } export default Login;

로그인 폼이 얼추 완성되었습니다. 이제 회원가입 링크를 눌러보세요. Register 을 채워주지 않았기때문에 비어있는 폼이 나타날 것입니다.

Register 컴포넌트 내용 채우기

그럼 이제, Register 컴포넌트를 채워줍시다. Login 과 매우 비슷한데, 차이점은 아이디 값을 필요로하고, 비밀번호 확인이 필요하기 때문에 인풋이 두개 더 있고, 하단 버튼과 우측정렬 링크의 텍스트가 다릅니다.

여기서 아이디는 username 입니다. 회원 인증용으로 사용된다기보다는, 서비스상에서 나타나는 이름입니다. 한국 인터넷상에서는 유저네임이라는 표현보다는 아이디가 더 익숙하니, 이렇게 부르도록 하겠습니다.

src/containers/Auth/Register.js

import React, { Component } from ‘react’ ; import { AuthContent, InputWithLabel, AuthButton, RightAlignedLink } from ‘components/Auth’ ; class Register extends Component { render() { return ( 회원가입 로그인 ); } } export default Register;

로그인 컴포넌트와 매우 비슷하죠?

인풋이 4개나 있으니까 조금 복잡해보입니다. 이 복잡해 보이는 느낌은, placeholder 를 더 연하게 해주면 어느정도 해소 된답니다.

InputWithLabel 컴포넌트에서 인풋의 ::placeholder 를 통하여 색상을 변경하세요.

src/components/Auth/InputWithLabel.js – Input

const Input = styled.input ` width: 100%; border: 1px solid ${oc.gray[3]} ; outline: none; border-radius: 0px; line-height: 2.5rem; font-size: 1.2rem; padding-left: 0.5rem; padding-right: 0.5rem; ::placeholder { color: ${oc.gray[3]} ; } ` ;

조금은 눈이 편하지지 않았나요? 사용자는 폼에 인풋이 더 적게 있을수록 편안함을 느낍니다. 여러분이 만약에 여기서 유저경험을 더욱 최적화 하고 싶다면, 회원가입 과정에서 뷰를 하나 더 만들어서 아이디 값만 받는 폼을 만들면 됩니다.

이제 어느정도 로그인을 위한 유저 인터페이스가 완성되었습니다. 다음 섹션에서는, 각 인풋에 상태를 연결시키는 부분을 다뤄보도록 하겠습니다.

2021.09.17 React 로그인, 회원가입(1)

2021.09.17 React 로그인, 회원가입(1)_정리노트

아….날ㄹ라가썽…..3시간동안 적은거 다날라갔어….배터리 분명 충전해놨는데….0퍼되서 꺼져서 3시간 날라갔어…너무 참혹하다…….ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠ 내 맥북이 이제 수명을 다했나봐…. 아 진짜 개 열ㄹ심히적었는데

결론 … 임시저장을 제발 생활화 합시다 제ㄹ…….ㅂ ㅏ ㄹ…..

오늘은 프로젝트 세팅에 이어서 로그인, 회원가입 UI 를 만들고 리덕스를 이용해 상태관리 , 또 백엔드에 만들어 두었던 API 요청까지라 역대급으로 포스팅일ㄹ 길 것 같다.. 왜냐 UI 만들고 리덕스 하는 도중에 꺼졌는데… 그거 포스팅이 3시간 걸렸거든…껄껄ㄹ

침착하고…. 조금 전보다는 생략되겠지만 최대한 다시 흐름 복습한다 생각하고 다시해보자! 뺘샤 ㅠ

적다보니 너무 많아져서 이거는 최초로..2편으로 나누겠다 후.. 이 포스팅에서는 UI 를 만들고 리덕스 연결해서 상태관리 하는 것까지 하고 끝끝!!!!!

먼저 UI 로 간다!

src/components/auth/AuthForm.js ( 새로 생성 )

앞으로는 계속 스타일 컴포넌트로 스타일링 할 것임! 그리고 컴포넌트들의 최상위도 감싸줄 때 Block 이라는 네이밍 규칙을 써줄텐데, Wrapper, Styled 처럼 자신이 원하는대로 써줘도 된다.

그리고 레이아웃을 보여주는 template 컴포넌트도 작성해줄 예정.

src/components/auth/AuthTemplate.js ( 새로 생성 )

그런데 이렇게 계속 반복되는 코드가 한번에 짠하고 나타나면 을매나 좋을깡

근데 사실 난 이미 책에서 소개한 한 익스텐션을 쓰고 있었는데, 얘를 커스텀화 하면 이거또한 한번에 쳐줄 수 있음.

얘를 깔아서 쓰고 있었는데, 얘가 하는 일이 뭐냐면

rsc 는 함수형 컴포넌트, rcc 는 클래스형 컴포넌트를 만들어주는 줄임말임 홀홀

그니까 얘를 커스텀 해주면 Block 이 들어가게 해서 스타일 컴포넌트와 함께 짠하고 나타낼 수 있음!

https://snippet-generator.app/

여기로 들어가서

좌측 상단에 Description 부분에는 우리가 쓸 user snippet 의 이름을, Tab trigger 부분에는 우리가 rsc 처럼 써줄 줄임말을 쓰고,

${TM_FILENAME_BASE} 는 우리가 적어준 파일의 이름을 들고옴. 그러니까 우리는 파일 이름 + Block 이니께 저렇게 좌측에 Template 코드를 복붙해서 ${TM_FILENAME_BASE} 얘만 바꿔주자 그러고 Copy snippet!

그러고 설정 아이콘에 User Snippet 탭을 들어가서

javascriptreact.json 클릭!

복사해둔 snippet 붙여넣기!!!

크크 마지막으로

vs code 하단에 자바스크립트라고 되어 있을거임 얘를

Configure File Association for .js 탭에서

자바스크립트 리액트로 설정! 그러면 js 코드 앞에 있던 JS 파일 아이콘이 리액트 로고로 바뀌면서 밑에는 자바스크립트 리액트로 설정이 될 것임.

그러고 우리가 설정해준 줄임말을 쓰게 되면!!!

아이 편하다 ㅎㅎ 매우 유용한 기능인듯.

이제는 AuthTemplate 은 레이아웃을 보여주고 AuthForm을 크게 감쌀거라서 자식 요소들을 렌더링해주세요~ 라고 해줘야한다.

그럴 때 쓰는 것이 children props!

src/componets/auth/AuthTemplate

import React from ‘react’; import styled from ‘styled-components’; const AuthTemplate = ({children}) => { // 부모 컴포넌트 안에 있는 자식 컴포넌트 요소 띄우기 return ( {children} ) ; }; export default AuthTemplate;

요롷게 넘겨주고

src/pages/LoginPage

// login import React from ‘react’; import AuthTemplate from ‘../components/auth/AuthTemplate’; import AuthForm from ‘../components/auth/AuthForm’; const LoginPage = () => { return( ); }; export default LoginPage;

src/pages/RegisterPage

// register import React from ‘react’; import AuthTemplate from ‘../components/auth/AuthTemplate’; import AuthForm from ‘../components/auth/AuthForm’; const RegisterPage = () => { return ( ); }; export default RegisterPage;

이렇게 해서 AuthForm 이라는 글씨가 뜨면 성공! children props 를 넣어주어야 잘 작동한다!

이제 레이아웃인 AuthTemplate 을 완성 시키자 ㄱ

src/components/auth/AuthTemplate

import React from ‘react’; import { Link } from ‘react-router-dom’; import styled from ‘styled-components’; // palette import import palette from ‘../../lib/styles/palette’; // 회원가입 / 로그인 페이지의 레이아웃 담당 const AuthTemplateBlock = styled.div` position: absolute; left: 0; right: 0; top: 0; bottom: 0; right:0; /* 내가 설정해놓은 paltte 에서 2번째 회색을 쓰겠어 */ background : ${palette.gray[2]}; display: flex; flex-direction:column; justify-content: center; align-items: center; `; // white box const WhiteBox = styled.div` .logo-area { display: block; padding-bottom: 2rem; text-align:center; font-weight: bold; /* 글자 간격 */ letter-spacing:2px; } /* 윤곽선 4면 전부 그림자로 입체감줌 */ box-shadow: 0 0 8px rgba(0,0,0,0.025); padding: 2rem; width: 360px; background: white; border-radius: 2px; ` const AuthTemplate = ({children}) => { // 부모 컴포넌트 안에 있는 자식 컴포넌트 요소 띄우기 return ( {/* 전부 스타일 컴포넌트로 만들어주지 않고 가독성을 위해 css selector 사용 */}

TITLE

{children} ) ; }; export default AuthTemplate;

이렇게 스타일 컴포넌트로 스타일링 해주고, 굳이 전부 스타일 컴포넌트로 만들지 않고, 가독성을 위해 css selector 로 하나 만들어쥼.

으어… 실행화면 다 날라갔지만,,, 이쁜 하얀색 박스와 함께 AuthForm 글씨가 흰 박스 안에 뜬다면 성공이다 ㅎㅅㅎ

이제는 ? 레이아웃을 만들어주었으니, 자식 요소인 form 으로 꼬!

src/components/auth/AuthForm

import React from ‘react’; import { Link } from ‘react-router-dom’; import styled from ‘styled-components’; // palette import import palette from ‘../../lib/styles/palette’; // Button component import import Button from ‘../common/Button’; // 회원가입 or 로그인폼 보여줌. const AuthFormBlock = styled.div` h3{ margin: 0; color:${palette.gray[8]}; margin-bottom: 1rem; } `; // button margin const ButtonWithMarinTop = styled(Button)` margin-top: 1rem; ` // styled input const StyledInput = styled.input` font-size:1rem; border:none; border-bottom: 1px solid ${palette.gray[5]}; padding-bottom: 0.5rem; outline: none; width: 100%; &:focus{ color: $oc-teal-7; border-bottom:1px solid ${palette.gray[7]} ; } /* Scss 에서 쓰는 요소가 서로 반복될 때 margin-top 을 줌 >>> input 과 input 사이에 margin-top 줌. */ &+&{ margin-top: 1rem; } ` // 폼 하단에 회원가입 링크 style const Footer = styled.div` margin-top:2rem; text-align : right; a { color : 1px solid ${palette.gray[6]}; text-decoration:underline; &:hover{ color:1px solid ${palette.gray[9]} } } ` const textMap = { login:’로그인’, register : ‘회원가입’ } const AuthForm = ({type }) => { const text = textMap[type]; return (

{text}

{/* autocomplete 속성 >> 인풋에 자동완성하는 속성 username 은 사용자 이름 , new-password 는 보통 비밀번호 자동완성 막기 위해서 새로운 비밀번호나 비밀번호 확인란에 들어간다는뎅 ㅎ.. 머 일단 책은 이렇고 나는 나중에 보고 current-password 가 더 맞을거 같아서 임의로 바꿨음. */} {/* type 이 회원가입이면, 비밀번호 확인 인풋 추가 */} {type === ‘register’ &&( ) } {text}

{type === ‘login’ ? ( 회원가입 ):( 로그인 ) }
); }; export default AuthForm;

자 여기서 짚고 넘어가야할 점 정리.

먼저 보면 type 이라는 props 를 정해주었다. 우리는 요 하나의 form 컴포넌트를 가지고 로그인 , 회원가입을 띄울 것이기 때문쓰.

그래서

const textMap = { login:’로그인’, register : ‘회원가입’ }

이 부분에서 로그인과 회원가입 타입을 나눠서 text 도 바꿔주고, 회원가입일 때는 비밀번호 확인이라는 인풋을 하나 더 보여주도록 설정해준 것이다.

{/* type 이 회원가입이면, 비밀번호 확인 인풋 추가 */} {type === ‘register’ &&( ) }

이렇게 회원가입을 할 때는 비밀번호 확인이라는 인풋을 하나 더 띄워주고,

{type === ‘login’ ? ( 회원가입 ):( 로그인 ) }

마찬가지로 링크 또한 타입에 따라 회원가입, 로그인으로 다르게!!!

그러고 나서,

src/pages/LoginPage

// login import React from ‘react’; import AuthTemplate from ‘../components/auth/AuthTemplate’; import AuthForm from ‘../components/auth/AuthForm’; const LoginPage = () => { return( ); }; export default LoginPage;

src/pages/RegisterPage

// register import React from ‘react’; import AuthTemplate from ‘../components/auth/AuthTemplate’; import AuthForm from ‘../components/auth/AuthForm’; const LoginPage = () => { return( ); }; export default LoginPage;

type props 를 Login, RegisterPage 로 넘겨준다.

실행 화면

http://localhost:3000/login

http://localhost:3000/register

홀홀 이렇게 떴는감 ~???

이렇게 뜨면 안됨 ㅎ

ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 버튼이 지금 왼쪽에 작게 치우쳐있다면 성공한 것임

나는 버튼에 대한 설정을 줬기 때문이다.

src/components/common/Button

import React from ‘react’; // css import import styled,{css} from ‘styled-components’; import palette from ‘../../lib/styles/palette’; // button styling const StyledButton = styled.button` border: none; border-radius: 4px; font-size: 1rem; font-weight: bold; padding: 0.25rem 1rem; color: white; outline: none; cursor: pointer; background: ${palette.violet[6]}; &:hover { background: ${palette.violet[4]}; } /* fullWidth props =ture */ ${props => props.fullWidth && css` padding-top: 0.75rem; padding-bottom: 0.75rem; width: 100%; font-size: 1.125rem; ` } /* fullWidth cyan =ture */ ${ props => props.cyan && css` background: ${palette.cyan[5]}; &:hover{ background: ${palette.cyan[4]}; } ` } `; // Button 에 받아오는 props 를 모두 styledButton 에 전달한다는 의미 const Button = (props) => { return ; }; export default Button;

저번에 세팅할 때 이미 props 를 모두 전달한다고 했으니까 스타일 컴포넌트에서 유용한 기능인 props가 true 이면 해당 스타일이 적용되도록 한것! 이렇게 fullWidth, cyan props 를 설정해줬으면 ??

src/components/auth/AuthForm

요 버튼 컴포넌트에 해당 props 의 이름을 적어주면 true 로 인식해서 width 100% 가 잘 적용이 될것이다! 근데 또 보면 버튼 컴포넌트 이름이 이상하지 않은가 ? ㅎㅅㅎ

왜겠엉 내가 직접 다른 컴포넌트로 지어줬으니께 껄꺼

// button margin const ButtonWithMarinTop = styled(Button)` margin-top: 1rem; `

이렇게 버튼을 직접 가져와서 새로운 컴포넌트 이름으로 정의해주면!!!!

이렇게 잘뜨면 성공 ㅎ

우왕 그래도 정리해서 적으니까 분량 많이 줄었군 ㅎㅁㅎ 물론 끝이 아니지 겨우 UI 완성했을뿐일라구 후후…ㅠ

이제 리덕스로 회원가입/로그인폼 상태 관리해주러 가야함

src/modules/auth

import { createAction, handleActions } from ‘redux-actions’; // produce import import produce from ‘immer’; // // sample 액션 타입 정의 // // module/ACTION_TYPE. 액션 타입은 대문자로, 앞에 모듈을 붙여주어야 액션 이름 중첩을 방지할 수 있음. // const SAMPLE_ACTION = ‘auth/SAMPLE_ACTION’; const CHANGE_FIELD = ‘auth/CHANGE_FIELD’; const INITIALIZE_FORM = ‘auth/INITIALIZE_FORM’; // // 액션 생성자. createAction 함수는 매번 객체를 직접 만들어 줄 필요 없이 더욱 간단하게 액션 생성 함수를 선언할 수 있음. 사용으로 액션 추가 데이터는 payload 사용. // // 액션 생성자는 export // export const sampleAction = createAction(SAMPLE_ACTION); export const changeField = createAction( // 추가 데이터 생성은 payload. CHANGE_FIELD, ({form,key,value}) =>({ form, // register, login key, // username , passowrd, passowrdConfirm value // 실제로 바꾸려는 값 }) ); export const initializeForm = createAction(INITIALIZE_FORM, form => form); //register , login // 초기 상태 정의 const initialState = { register: { username: ”, password: ”, passwordConfirm: ” }, login: { username: ”, password: ” }, } // 리듀서 함수 // 리듀서 함수도 더 간단하고 가독성 높게 사용하기 위해 handleActions 함수 사용 // 리듀서 함수는 export default 로 const auth = handleActions( { // 전부 다 추가 데이터가 payload 면 헷갈리니까 객체 비구조화 할당으로 좀 더 직관적으로 사용 [CHANGE_FIELD]: (state, { payload: { form, key, value } }) => // 불변성 유지를 위해 immer 라이브러리 사용 produce(state, draft => { draft[form][key] = value; // 예: state.register.username을 바꾼다 }), [INITIALIZE_FORM]: (state, { payload: form }) => ({ // 얘는 오히려 immer 쓰면 복잡해지니까 spread 사용 …state, [form]: initialState[form], }), }, initialState, ); export default auth;

역시..리덕스는 어려웡…쿨쩍 다른거는 그려러니하고 넘어가는데 아직 리듀서함수 부분은 공부가 더 필요할 듯하다. 그래도 최대한 흐름 정리하면서 무엇을 쓰고 무엇을 쓰고 정도는..주석으로 달아보았다.

구글링과 내 블로그 포스팅인 react-redux 를 보고 참고했는데 내가 이거 너무 책따라 줄줄쳐서 비공개로 해놨네 ㅎ 모르는거는 괜히 올려놓으면 안하느니만 못하니…쨋든 흐름을 이렇게 정리해봐쑴

도움이 되었다면 좋겠지만 쪼다는 여기까지인가보오.. 그래도 주석해놓은 기본 틀이랑 비교하면서 요롷게요롷게 쓰는건강 ?? 하면서 같이 음음 해줬으면 좋겠다

https://velog.io/@jeffyoun/React-Redux-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EC%A0%95%EB%A6%AC

참고로 나는 이분걸 참고했다. 맨 마지막 부분에 핵심만 정리해놓으신 노트 또한 따로 분리되어 있어서 나는 한번 더 읽기도 좋았따! 나랑 같은 책으로 공부하시는거 같아 내심 기쁨…ㅎ…..ㅋㅋㅋㅋㅋ쨋든 아직 너무 낯설지만 그래도 점점 익숙해지다보면, 나도 리덕스는 이래서 좋으니까 써보고 아니면 안써야지를 판단할 때가 오겠지 ㅎㅅㅎ

이제 컴포넌트에서 리덕스 스토어에 접근해서 상태를 받아오고, 액션을 디스패치해야겠지 ???? 그게 무어였지!?????

컨테이너 컴포넌트…끌끌

비공개 포스팅에서 발그림으로 그렸던 거 캡쳐쓰

아주 그냥 책을 줄ㄹ줄 써놨더라 그래서 혼자 근데 줄줄 읽음 ㅎ

쨋든 컨테이너 컴포넌트 만들러 ㄲ

src/containers/auth/LoginForm.js ( 새로 생성 )

// useEffect import import React,{useEffect} from ‘react’; // useSelector, useDispatch import import { useDispatch, useSelector } from ‘react-redux’; // auth module 액션 생성함수 import import { changeField, initializeForm } from ‘../modules/auth’; // AuthForm import import AuthForm from ‘../components/auth/AuthForm’; const LoginForm = () => { const dispatch = useDispatch(); const { form } = useSelector( ({ auth }) => ( { form : auth.login })); // input change event 로 액션 디스패치. 디스패치 : 액션을 발생시키는 것. const onChange = e => { const { value, name } = e.target; // 액션 생성 함수 import dispatch( changeField({ form:’login’, key:name, value }) ); }; // form submit event const onSubmit = e => { e.preventDefault(); // 구현 예정 } // 컴포넌트 초기 렌더링시 form 초기화 useEffect(()=>{ // 액션 생성 함수 import dispatch(initializeForm(‘login’)); },[dispatch]); return ( ); }; export default LoginForm;

아웅..길다 여기서 또 정리하자면, 컨테이너 컴포넌트를 만들 때 쓰는 connect 함수를 쓰지 않고 useSelector, useDispath hook 을 썼음

useSelector

connect 대신에 리덕스 state를 조회할 수 있다.

useDispath

생성한 action 을 발생시키는 hook. 만들어둔 액션 생성함수를 import 하여 사용

또 디스패치는 form onSubmit, input onChange 이벤트가 발생할 때 되도록 구현했다. 또 useEffect 를 써서 초기 렌더링시 form 초기화를 시키는 작업을 했는데, 얘를 안하게 되면 우리가 페이지를 이동하고 다시 이 페이지로 돌아오게 되었을 때 유저가 썼던 값이 그대로 남아있기 때문 ㅇㅇ!

그러고 AuthForm type 과 함께 props를 설정해주었음.

후.. 이제 컨테이너 컴포넌트를 만들었다면

src/pages/LoginPage

// login import React from ‘react’; import AuthTemplate from ‘../components/auth/AuthTemplate’; import AuthForm from ‘../components/auth/AuthForm’; // LoginForm import import LoginForm from ‘../containers/LoginForm’; const LoginPage = () => { return( ); }; export default LoginPage;

AuthForm 대신에 LoginForm 으로 바꿔주자

그리고 나서 우리가 컨테이너 컴포넌트에서 props 값을 AuthForm 으로 넘겨줬으니까 AuthForm에서 받을 차례!

src/components/auth/AuthForm

import React from ‘react’; import { Link } from ‘react-router-dom’; import styled from ‘styled-components’; // palette import import palette from ‘../../lib/styles/palette’; // Button component import import Button from ‘../common/Button’; // 회원가입 or 로그인폼 보여줌. const AuthFormBlock = styled.div` h3{ margin: 0; color:${palette.gray[8]}; margin-bottom: 1rem; } `; // button margin const ButtonWithMarinTop = styled(Button)` margin-top: 1rem; ` // styled input const StyledInput = styled.input` font-size:1rem; border:none; border-bottom: 1px solid ${palette.gray[5]}; padding-bottom: 0.5rem; outline: none; width: 100%; &:focus{ color: $oc-teal-7; border-bottom:1px solid ${palette.gray[7]} ; } /* Scss 에서 쓰는 요소가 서로 반복될 때 margin-top 을 줌 >>> input 과 input 사이에 margin-top 줌. */ &+&{ margin-top: 1rem; } ` // 폼 하단에 회원가입 링크 style const Footer = styled.div` margin-top:2rem; text-align : right; a { color : 1px solid ${palette.gray[6]}; text-decoration:underline; &:hover{ color:1px solid ${palette.gray[9]} } } ` const textMap = { login:’로그인’, register : ‘회원가입’ } const AuthForm = ({type , form , onChange, onSubmit }) => { const text = textMap[type]; return (

{text}

// form onSubmit

// input onChange,value // input onChange,value {/* type 이 회원가입이면, 비밀번호 확인 인풋 추가 */} {type === ‘register’ &&( // input onChange,value ) } {text}

{type === ‘login’ ? ( 회원가입 ):( 로그인 ) }
); }; export default AuthForm;

js 주석으로 일부러 헷갈릴까봐 여기서 작업했더니 똑같이 안보이네 끌끌 코드 복붙이나, 아니면 같이 어디에다가 props 넣어야하는지 보면서 치면 될듯..!

나도 모듈부터 사실 헷갈려서 계속 눈이빠져라봄….

실행 화면

인풋이 바뀔 때마다 액션이 발생하고, value 값도 잘 들어간당

회원가입도 얘처럼 해주면 되겠균 LoginForm 복사해서 RegisterForm 도 만들어주기.

src/containers/auth/RegisterForm.js ( 새로 생성 )

// useEffect import import React,{useEffect} from ‘react’; // useSelector, useDispatch import import { useDispatch, useSelector } from ‘react-redux’; // auth module 액션 생성함수 import import { changeField, initializeForm } from ‘../modules/auth’; // AuthForm import import AuthForm from ‘../components/auth/AuthForm’; const RegisterForm = () => { const dispatch = useDispatch(); const { form } = useSelector( ({ auth }) => ( { form : auth.register })); // input change event 로 액션 디스패치. 디스패치 : 액션을 발생시키는 것. const onChange = e => { const { value, name } = e.target; // 액션 생성 함수 import dispatch( changeField({ form:’register’, key:name, value }) ); }; // form submit event const onSubmit = e => { e.preventDefault(); // 구현 예정 } // 컴포넌트 초기 렌더링시 form 초기화 useEffect(()=>{ // 액션 생성 함수 import dispatch(initializeForm(‘register’)); },[dispatch]); return ( ); }; export default RegisterForm;

이름 LoginForm >> RegisterForm 으로 변경하고, login 이 적혀있던 부분만 register 로 바꿔주면 됨.

src/pages/RegisterPage

// register import React from ‘react’; import AuthTemplate from ‘../components/auth/AuthTemplate’; import AuthForm from ‘../components/auth/AuthForm’; // regitserform import import RegisterForm from ‘../containers/RegisterForm’; const RegisterPage = () => { return ( ); }; export default RegisterPage;

듀근듀근 잘 되려나

실행 화면

이쯤에서 블로그 날라가서 그런가 멘탈이 터져서 몇번이나 사실 고쳤음 ㅎ….. 정신 똑바로 차리고 봐야지…

음…. ㅋㅋㅋㅋㅋㅋㅋㅋㅋ 이걸…쓰다보니까 너무 많아서 나누게 됐는데 정말 결국 한 포스팅을 두번 쓴 셈이네 ㅎㅅㅎ … 젠장….

그래도 UI 쪽 부분 정리안했으면 난리났을거 같애서 긍정…적으로 생각하겠음…추석 전에 거하게 액뗌했다..ㅠ 나는 오늘 새벽에 2편을 쓰기 시작해서…언제 마무리 될 지는 모르겠으나…! 다시 바로 2편으로 오지 그러면 안녕!

[리액트/노드 기초] 로그인 시스템 만들기 (8) – 회원가입 페이지, 로그아웃 만들기

반응형

이번 글에서는 회원가입 페이지와 로그아웃 기능을 만들어 보겠습니다.

회원가입 페이지 만들기

회원가입 페이지의 레이아웃은 기본적으로

로그인 페이지와 거의 비슷한 모습을 하고 있습니다.

따라서 로그인 페이지를 변형하여 다음과 같은 기본 형태를 만들어줍니다.

import React, { useState } from ‘react’; import { useDispatch } from ‘react-redux’; import { withRouter } from ‘react-router-dom’; function RegisterPage(props) { // redux의 dispatch const dispatch = useDispatch(); // react hook에서 state 사용 const [Email, setEmail] = useState(”); const [Password, setPassword] = useState(”); const [Name, setName] = useState(”); const [ConfirmPassword, setConfirmPassword] = useState(”); // handler 함수들 const onEmailHandler = (event) => { setEmail(event.currentTarget.value); }; const onNameHandler = (event) => { setName(event.currentTarget.value); }; const onPasswordHandler = (event) => { setPassword(event.currentTarget.value); }; const onConfirmPasswordHandler = (event) => { setConfirmPassword(event.currentTarget.value); }; return (


); } export default withRouter(RegisterPage);

다음으로 회원가입 정보를 제출했을 때 처리하는 코드를 만들어 주겠습니다.

로그인 페이지와 마찬가지로 _actions/user_action에 만들어줍니다.

// client/src/_actions/user_action.js import { LOGIN_USER, REGISTER_USER } from ‘./types’; export function registerUser(dataToSubmit) { // axios를 이용해 login 요청을 보내고 response.data를 반환하여 request에 넣어준다. const request = axios.post(‘/api/users/register’, dataToSubmit).then((response) => response.data); return { type: REGISTER_USER, payload: request, }; }

회원가입 과정 또한 axios를 이용해 이미 만들어놓은 서버에 요청을 보내면 됩니다.

type도 types.js 파일에 저장해줍니다.

// client/src/_actions/types.js export const LOGIN_USER = ‘login_user’; export const REGISTER_USER = ‘register_user’;

user_reducer에도 state를 변경해주는 reducer를 만들어줍니다.

// client/src/_reducers/user_reducer.js import { LOGIN_USER, REGISTER_USER } from ‘../_actions/types’; export default function (state = {}, action) { switch (action.type) { case LOGIN_USER: return { …state, loginSuccess: action.payload }; case REGISTER_USER: return { …state, registerSuccess: action.payload }; default: return state; } }

이제 마지막으로 컴포넌트에서 이러한 과정들을 처리하는 핸들러를 만들어주도록 하겠습니다.

// client/src/components/views/RegisterPage.js … const onSubmitHandler = (event) => { // 태그의 기본 기능으로 리프레쉬 되는 것을 방지. event.preventDefault(); if (Password !== ConfirmPassword) { return alert(‘비밀번호 확인이 일치하지 않습니다.’); } let body = { email: Email, name: Name, password: Password, }; // action을 dispatch해준다. dispatch(registerUser(body)).then((response) => { if (response.payload.success) { props.history.push(‘/’); } else { alert(‘회원가입에 실패했습니다.’); } }); }; …

이렇게 회원가입 페이지가 완성되었습니다.

최종 코드는 다음과 같습니다.

import React, { useState } from ‘react’; import { useDispatch } from ‘react-redux’; import { registerUser } from ‘../../../_actions/user_action’; import { withRouter } from ‘react-router-dom’; function RegisterPage(props) { // redux의 dispatch const dispatch = useDispatch(); // react hook에서 state 사용 const [Email, setEmail] = useState(”); const [Password, setPassword] = useState(”); const [Name, setName] = useState(”); const [ConfirmPassword, setConfirmPassword] = useState(”); // handler 함수들 const onEmailHandler = (event) => { setEmail(event.currentTarget.value); }; const onNameHandler = (event) => { setName(event.currentTarget.value); }; const onPasswordHandler = (event) => { setPassword(event.currentTarget.value); }; const onConfirmPasswordHandler = (event) => { setConfirmPassword(event.currentTarget.value); }; const onSubmitHandler = (event) => { // 태그의 기본 기능으로 리프레쉬 되는 것을 방지. event.preventDefault(); if (Password !== ConfirmPassword) { return alert(‘비밀번호 확인이 일치하지 않습니다.’); } let body = { email: Email, name: Name, password: Password, }; // action을 dispatch해준다. dispatch(registerUser(body)).then((response) => { if (response.payload.success) { props.history.push(‘/’); } else { alert(‘회원가입에 실패했습니다.’); } }); }; return (


); } export default withRouter(RegisterPage);

로그아웃 기능 만들기

로그아웃 기능 또한 노드 서버에서 구현해 놓았기 때문에

프론트엔드에서 요청만 보내면 됩니다.

랜딩 페이지에 버튼을 만들어 간단하게 구현하겠습니다.

// client/src/components/views/LandingPage.js import React, { useEffect } from ‘react’; import axios from ‘axios’; import { withRouter } from ‘react-router-dom’; function LandingPage(props) { const onClickHandler = () => { axios.get(‘/api/users/logout’).then((response) => { if (response.data.success) { return props.history.push(‘/login’); } else { return alert(‘로그아웃에 실패했습니다.’); } }); }; return (

LandingPage

); } export default withRouter(LandingPage);

로그아웃 기능은 리덕스를 이용하지 않고

핸들러 자체에 로그아웃 요청을 보내는 코드를 작성하였습니다.

다음 글에서는 마지막으로 하이어오더 컴포넌트를 이용해 유저 인증 기능을 구현해보도록 하겠습니다.

반응형

React로 블로그 만들기 26. 회원가입 구현하기

1. 이전 주소로 외부에 공유된 글은

3개월간 새로운 주소로 연결을 지원하며

이후 언제든 연결이 끊길 수 있습니다.

2. 블로그 아이디는 한번 변경하면

다시 변경이 불가능합니다.

변경하시겠습니까?

React | 회원가입 기능 구현하기

현재 email창엔 ‘@’가 포함되어야 하고, password는 5자리 이상이어야 버튼이 활성화되도록

유효성 로직을 포함한 회원가입을 진행해보고자 한다.

Step.1 : state 설정

최상위 컴포넌트의 state/fetch 함수 부분 (중요 부분만 발췌)

// state 부분 constructor(props) { super(props); this.state = { first_name: ‘Donghee’, last_name: ‘Kim’, email: ”, password: ”, phone_number: ‘01011111111’, gender: ‘w’, birth: ‘1995-12-27’, }; } //fetch 함수 부분 (then 함수 부분은 생략) fetch(‘API주소’, { method: ‘POST’, body: JSON.stringify({ first_name: ‘Donghee’, last_name: ‘Kim’, email: this.state.email, password: this.state.password, phone_number: ‘010-1111-1111’, gender: ‘w’, birth: ‘1995-12-27’, }), }

최상위 컴포넌트의 state에 빈 문자열로 email, password를 주고,

fetch함수를 통해 API주소가 들어올 경우 각각의 state값은 현 state의 email, password값으로 업데이트 되도록 했다.

Step.2 : input값을 저장하는 함수 활용

email, password input에 준 속성들

input의 값을 저장하는 handleInput 함수

handleInput = e => { const { value, name } = e.target; this.setState({ [name]: value }); };

email, password input에 각각 email, password로 name 속성 을 주고,onChange이벤트로 handleInput 함수를 주었다.

(원래 handleId, handlePw으로 나뉘어져있었는데 리팩토링하는 과정에서 하나로 합쳤다.)

handleInput함수에선 구조분해할당 활용!

input의 name 값(email, password)에 input에 입력된 값이 할당되도록 했다.

결과적으로 state의 email, password에 input에 입력된 값이 할당되는 셈이다.

Step.3 : API로 받아온 데이터와 비교

handleJoin = () => { fetch(‘API주소’, { method: ‘POST’, body: JSON.stringify({ first_name: ‘Donghee’, last_name: ‘Kim’, email: this.state.email, password: this.state.password, phone_number: ‘010-1111-1111’, gender: ‘w’, birth: ‘1995-12-27’, }), }) .then(response => response.json()) .then(response => { if (response.MESSAGE === ‘SUCCESS’) { return alert(‘회원가입 성공!’); } if (response.MESSAGE === ‘EMAIL ALREADY EXISTS’) { alert(‘이미 존재하는 이메일입니다’); } }); };

외부 데이터의 응답메세지를 활용해 성공할 경우 ‘회원가입 성공!’ 창을, 이메일이 이미 존재할 경우 ‘이미 존재하는 이메일입니다’ 창이 뜨도록 했다. 이 때 백엔드 측과 사전에 아래 사항을 꼭 확인해보아야한다.

➕ 프론트-백엔드 사전 확인사항

1. 각각의 데이터에 걸어둔 조건

(ex. 이메일엔 ‘@’가 포함되어야 한다 등)

2. key값

(실습 요건 상 이미 완성된 작업물을 가지고 다시 맞추어봤는데, key값이 달라 변경하느라 애를 먹었다.)

3. 프론트-백엔드 측이 같은 와이파이를 사용하고 있는지

4. 백엔드 측의 서버가 올바른 branch에서 잘 열려있는지

이렇게 회원가입 기능 마무리! 실제로 백엔드 페어의 데이터를 가지고 회원가입-로그인 실습까지 완료했다.

코드 전문

전체적인 흐름을 보기 위한, 해당 회원가입을 진행한 페이지의 코드 전문은 아래와 같다.

class LoginDonghee extends Component { constructor(props) { super(props); this.state = { first_name: ‘Donghee’, last_name: ‘Kim’, email: ”, password: ”, phone_number: ‘01011111111’, gender: ‘w’, birth: ‘1995-12-27’, }; } handleJoin = () => { fetch(‘API주소’, { method: ‘POST’, body: JSON.stringify({ first_name: ‘Donghee’, last_name: ‘Kim’, email: this.state.email, password: this.state.password, phone_number: ‘010-1111-1111’, gender: ‘w’, birth: ‘1995-12-27’, }), }) .then(response => response.json()) .then(response => { if (response.MESSAGE === ‘SUCCESS’) { return alert(‘회원가입 성공!’); } if (response.MESSAGE === ‘EMAIL ALREADY EXISTS’) { alert(‘이미 존재하는 이메일입니다’); } }); }; handleInput = e => { const { value, name } = e.target; this.setState({ [name]: value }); }; render() { return (

Westagram

비밀번호를 잊으셨나요?

); } } export default withRouter(LoginDonghee);

본 글은 2021년 8월 30일 개인 블로그(velog)에 작성된 글입니다.

[React] 회원가입 폼 validation 디자인 구현하기

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156

… function RegisterPage ( props ) { const dispatch = useDispatch (); // props , state -> 이 안에서는 state 를 변화시켜서 이 안의 데이터를 변화시킬 수 있음 // 입력한 이메일과 비밀번호를 서버에 넘길 수 있도록 state 에서 받고 있음 const [ Email , setEmail ] = useState ( “” ) const [ Password , setPassword ] = useState ( “” ) const [ Name , setName ] = useState ( “” ) const [ confirmPassword , setconfirmPassword ] = useState ( “” ) const onEmailHandler = ( event ) => { setEmail ( event . currentTarget . value ) } const onPasswordHandler = ( event ) => { setPassword ( event . currentTarget . value ) } const onNameHandler = ( event ) => { setName ( event . currentTarget . value ) } const onconfirmPasswordHandler = ( event ) => { setconfirmPassword ( event . currentTarget . value ) } const hasError = passwordEntered => Password . length < 5 ? true : false ; const hasNotSameError = passwordEntered => Password != confirmPassword ? true : false ; const onSubmitHandler = ( event ) => { event . preventDefault (); // 아무 동작 안하고 버튼만 눌러도 리프레쉬 되는 것을 막는다 if ( Password !== confirmPassword ){ return alert ( ‘ 비밀번호와 비밀번호 확인은 같아야 합니다. ‘ ) } let body = { email : Email , password : Password , name : Name , } dispatch ( registerUser ( body )) . then ( response => { if ( response . payload . success ){ alert ( ‘ 회원가입이 완료되었습니다! ‘ ); props . history . push ( ‘ /login ‘ ) // react 에서의 페이지 이동 코드 } else { alert ( ‘ Error!! ‘ ); } }) // 완료가 잘 되었을 경우 이동 } const classes = useStyles (); return ( < Container component = "main" maxWidth = "xs" > < CssBaseline /> < div className = { classes . paper } > < Avatar className = { classes . avatar } > < LockOutlinedIcon /> < Typography component = "h1" variant = "h5" > Messenger Sign Up < form className = { classes . form } noValidate onSubmit = { onSubmitHandler } > < Grid item xs = { 12 } > < TextField autoComplete = "fname" name = "firstName" variant = "filled" value = { Name } onChange = { onNameHandler } required fullWidth id = "firstName" label = "이름" autoFocus /> < Grid item xs = { 12 } > < TextField variant = "filled" required fullWidth value = { Email } onChange = { onEmailHandler } id = "email" label = "Email Address" name = "email" autoComplete = "email" /> < Grid item xs = { 12 } > < TextField variant = "filled" required fullWidth value = { Password } onChange = { onPasswordHandler } name = "password" error = { hasError ( ' password ' ) } // 해당 텍스트필드에 error 핸들러 추가 label = "Password(5글자 이상 필수)" type = "password" id = "password" autoComplete = "current-password" /> < Grid item xs = { 12 } > < TextField variant = "filled" required fullWidth value = { confirmPassword } onChange = { onconfirmPasswordHandler } name = "confirmPassword" error = { hasNotSameError ( ' confirmPassword ' ) } // 해당 텍스트필드에 error 핸들러 추가 helperText = { hasNotSameError ( ' confirmPassword ' ) ? " 입력한 비밀번호와 일치하지 않습니다. " : null } // 에러일 경우에만 안내 문구 표시 label = "Confirm Password" type = "password" id = "confirmPassword" autoComplete = "current-password" /> < Button type = "submit" fullWidth variant = "contained" onSubmit = { onSubmitHandler } color = "primary" className = { classes . submit } > 회원가입 < Grid container justify = "flex-end" > < Grid item > < Link href = "/login" variant = "body2" > 이미 가입하셨다면, 로그인해 주세요! < Box mt = { 5 } > ) }

[React] 회원가입 기능 구현 (MySQL / bcrypt / 쿠키)

2022.07.21 – [Coding/React] – [React] 고객관리 사이트 (Client) redux로 구현하기

1. MySQL 데이터베이스에 table 생성

2. 서버 구현

1) join 경로 post 요청시

customer_members 테이블에 데이터 추가하기

비밀번호는 암호화하여 저장

등록일은 Now()함수를 사용해서 현재 날짜를 저장

패스워드 암호화 알고리즘 라이브러리 – bcrypt 설치

npm install bcrypt

2) login 경로 post 요청시

usermail 값으로 일치하는 데이터를 조회(select)

입력받은 userpass를 암호화하여 조회한 데이터의 암호화된 값과 비교하여 일치하는지 확인

일치하면 조회한 데이터를 응답해줌

3. 클라이언트 구현

JoinForm.js 생성

1) 로그인 리듀서 작성

logincheck.js

2) Login 컴포넌트 생성

3) util 폴더 안에 cookie.js 생성

npm install react-cookie

https://www.npmjs.com/package/bcrypt

이 구문들을 사용할 것임 !

MIDDLEWARE_GREEN_CUSTOMER_SERVER

npm install bcrypt

설치 후

const bcrypt = require(‘bcrypt’); const saltRounds = 10;

맨 위에 이 코드 추가

// 포스트맨으로 회원가입 확인

비밀번호가 해쉬함수로 잘 변환됨

good 😊

// 포스트맨으로 로그인 확인

index.js // 회원가입, 로그인 요청 부분 추가

const express = require(“express”); const cors = require(“cors”); const app = express(); const port = 3001; const mysql = require(“mysql”); const fs = require(“fs”) const bcrypt = require(‘bcrypt’); const saltRounds = 10; const dbinfo = fs.readFileSync(‘./database.json’); // 받아온 json 데이터를 객체형태로 변경 JSON.parse const conf = JSON.parse(dbinfo) // connection mysql연결 createConnection() // connection.connect() 연결하기 // connection.end()연결종료 // connection.query(‘쿼리문’, callback함수) // callback(error, result, result의 field정보) const connection = mysql.createConnection({ host: conf.host, user: conf.user, password: conf.password, port: conf.port, database: conf.database }) app.use(express.json()); app.use(cors()); // app.get(“경로”, 함수) // connection.query(“쿼리문”, 함수) app.get(‘/customers’, async (req, res)=> { // connection.connect(); connection.query( “select * from customers_table”, (err, rows, fields)=> { // res.send(“고객정보입니다.”) res.send(rows) console.log(fields); } ) // connection.end(); }) app.get(‘/detailview/:no’, async (req, res)=> { const params = req.params; // const { no } = params; connection.query( `select * from customers_table where no=${params.no}`, (err, rows, fields)=> { res.send(rows[0]) } ) }) // 내가한 것 // // addCustomer post 요청이 오면 처리 // app.post(“/addCustomer”, (req, res)=>{ // const body = req.body; // const { c_name, c_phone, c_birth, c_gender, c_add, c_adddetail} = body; // if(!c_name || !c_phone || !c_birth || !c_gender || !c_add || !c_adddetail) { // res.send(“모든 필드를 입력해주세요”); // } else { // connection.query( // `insert into customers_table (name, phone, birth, gender, add1, add2) values (‘${c_name}’, ‘${c_phone}’, ‘${c_birth}’, ‘${c_gender}’, ‘${c_add}’, ‘${c_adddetail}’)`, // (err, rows,fields) => { // res.send(“등록되셨습니다.”) // } // ) // } // }) // addCustomer post 요청이 오면 처리 req => 요청하는 객체, res => 응답하는 객체 // mysql 쿼리 select / update / delete / insert // insert into 테이블(컬럼1, 컬럼2, 컬럼3, …) values(?, ?, ?) // query(“쿼리”, [값1, 값2, 값3, 값4, 값5, 값6], 함수) // insert into customers_table(name, phone, birth, gender, add1, add2) // values(?, ?, ?, ?, ?, ?) app.post(“/addCustomer”, async (req, res)=>{ console.log(req) // const body = req.body; const { c_name, c_phone, c_birth, c_gender, c_add, c_adddetail} = req.body; connection.query( // `insert into customers_table (name, phone, birth, gender, add1, add2) values (‘${c_name}’, ‘${c_phone}’, ‘${c_birth}’, ‘${c_gender}’, ‘${c_add}’, ‘${c_adddetail}’)`, “insert into customers_table(name, phone, birth, gender, add1, add2) values(?, ?, ?, ?, ?, ?)”, [c_name, c_phone, c_birth, c_gender, c_add, c_adddetail], (err, rows,fields) => { res.send(“등록되셨습니다.”) } ) }) // 삭제요청 쳐리 /detailview/${no} // delete from 테이블명 조건명 // delete from customers_table where no = no app.delete(‘/detailview/:no’, async (req, res)=> { const params = req.params; console.log(‘삭제’); connection.query( `delete from customers_table where no=${params.no}`, (err, rows, fields)=> { res.send(rows) } ) }) // 수정요청 // update 테이블이름 set 컬럼명 = 값 where no = 값 // update customers_table set name=”, phone=”, birth=”, gender=”, add1=”, add2=” where no= // http://localhost:3001/edit/1 app.put(‘/edit/:no’, async (req, res)=> { // 파라미터 값을 가지고 있는 객체 const params = req.params; const { c_name, c_phone, c_birth, c_gender, c_add, c_adddetail} = req.body; console.log(‘수정’); console.log(req.body); connection.query( `update customers_table set name=’${c_name}’, phone=’${c_phone}’, birth=’${c_birth}’, gender=’${c_gender}’, add1=’${c_add}’, add2=’${c_adddetail}’ where no=${params.no}`, (err, rows, fields)=> { res.send(rows) } ) }) // 회원가입 요청 app.post(“/join”, async (req,res)=> { // green1234 let myPlaintextPass = req.body.userpass; let myPass = “”; if(myPlaintextPass != ” && myPlaintextPass != undefined) { bcrypt.genSalt(saltRounds, function(err, salt) { bcrypt.hash(myPlaintextPass, salt, function(err, hash) { // Store hash in your password DB. myPass = hash; console.log(myPass); // 쿼리 작성 const { username, userphone, userorg, usermail } = req.body; // connection.query 인자 첫번째: 쿼리문, 두번째: 쿼리문에 들어갈 값, 세번째: 처리 되면 하는 애 connection.query(“insert into customer_members(username, userpass, userphone, userorg, usermail, regdate) values(?,?,?,?,?,DATE_FORMAT(now(),’%Y-%m-%d’))”, [username, myPass, userphone, userorg, usermail], (err, result, fields) => { console.log(result) console.log(err) res.send(“등록되었습니다.”) } ) }); }); } }) // 로그인 요청 app.post(‘/login’, async (req, res)=> { // usermail 값에 일치하는 데이터가 있는지 select 문 // userpass 암호화해서 쿼리 결과의 패스워드랑 일치하는지를 체크 const {usermail, userpass} = req.body; connection.query(`select * from customer_members where usermail = ‘${usermail}’`, (err, rows, fileds)=>{ if(rows != undefined) { if(rows[0] == undefined) { res.send(null) } else { // Load hash from your password DB. bcrypt.compare(userpass, rows[0].userpass, function(err, result) { // result == true if(result == true) { res.send(rows[0]) } else { res.send(‘실패’) } }); } } else { res.send(‘실패’) } } ) }) // 서버실행 app.listen(port, () => { console.log(“고객 서버가 돌아가고 있습니다.”) })

MIDDLEWARE_GREEN_CUSTOMER_CLIENT

npm install react-cookie

components/JoinForm.js

import React, { useState } from ‘react’; import { useNavigate } from ‘react-router-dom’; import { Table, TableBody, TableRow, TableCell } from ‘@mui/material’; import axios from “axios”; import { API_URL } from ‘../config/contansts’; const JoinForm = () => { const navigate = useNavigate(); const [formData, setFormData] = useState({ username: “”, userpass: “”, userpassck: “”, userphone:””, userorg:””, usermail:”” }) const onChange = (e) => { const { name, value } = e.target; setFormData({ …formData, [name]:value }) } const onSumbit = (e) => { // form에 원래 연결된 이벤트를 제거 e.preventDefault(); console.log(formData); // 전화번호가 숫자인지 체크하기 if(isNaN(formData.userphone)){ alert(‘전화번호는 숫자만 입력해주세요’); setFormData({ …formData, userphone: “” }) } // input에 값이 있는지 체크하고 // 입력이 다되어있으면 post전송 else if( formData.username !== “” && formData.userpass !== “” && formData.userphone !== “” && formData.userpassck !==”” && formData.userorg !== “” && formData.usermail !== “” ){ addMember(); } else { alert(‘모든 항목을 기입해주세요’); } } function addMember(){ axios.post(`${API_URL}/join`, formData) .then((res)=>{ alert(‘등록되었습니다.’); navigate(“/”); }) .catch((e)=> { console.log(e); }) } return (

신규 고객 등록하기

이름 비밀번호 비밀번호체크 연락처 이메일 소속

); }; export default JoinForm;

components/Login.js

import React, { useState } from ‘react’; import { Link, useNavigate } from ‘react-router-dom’; import axios from ‘axios’; import { API_URL } from ‘../config/contansts’; import { setCookie } from ‘../util/cookie’; import { goToHome, setLogin } from ‘../modules/logincheck’; import { useDispatch } from ‘react-redux’; const Login = () => { const dispatch = useDispatch(); const navigate = useNavigate(); const [ loginData, setLoginData ] = useState({ usermail: “”, userpass: “”, }) const onChange = (e) => { const { name, value } = e.target; setLoginData ({ …loginData, [name]: value }) } const onSubmit = (e) => { e.preventDefault(); // input에 입력했는지 체크 if(loginData.usermail === ” || loginData.userpass === ”) { alert(‘이메일과 비밀번호를 입력해주세요’); } else { axios.post (`${API_URL}/login`, loginData) // 로그인이 되었을 때 .then(result => { let { usermail, username } = result.data; console.log(result); // usermail에 값이 있을 때 if(usermail !== null && usermail !== ” && usermail !== undefined) { alert(‘로그인되었습니다.’); // 현재시간 객체를 생성 let expires = new Date(); // 60분 더한 값으로 변경 expires.setMinutes(expires.getMinutes()+60) setCookie(‘usermail’, `${usermail}`, {path: ‘/’, expires}); setCookie(‘username’, `${username}`, {path: ‘/’, expires}); dispatch(setLogin()); dispatch(goToHome(navigate)); } }) .catch(e => { console.log(e); alert(‘ssssssssss 비밀번호를 확인해주세요’); }) } } return (

); }; export default Login;

components/header.js

import React, { useEffect } from ‘react’; import { Link } from ‘react-router-dom’; import { setLogout } from ‘../modules/logincheck’ import { useDispatch, useSelector } from ‘react-redux’; import { getCookie, removeCookie } from ‘../util/cookie’; const Header = () => { const uname = getCookie(‘username’); const isLogin = useSelector(state=>state.logincheck.isLogin); const dispatch = useDispatch(); const logoutClick = () => { removeCookie(‘username’); removeCookie(‘usermail’); dispatch(setLogout()); } useEffect(()=>{ // setLogin(true); },[isLogin]); return (

); }; export default Header;

modules/index.js

import { combineReducers } from “redux”; import customers from ‘./customers’; import logincheck from “./logincheck”; const rootReducer = combineReducers({ customers, logincheck }); export default rootReducer;

modules/logincheck.js

// 리덕스 액션타입, 액션 생성함수, 초기값, 리듀서 const SET_LOGIN = “SET_LOGIN”; const SET_LOGOUT = “SET_LOGOUT”; // 액션 생성함수 // const setLogin = () => { // return { // type: SET_LOGIN // } // } export const setLogin = () => ({ type: SET_LOGIN }) export const setLogout = () => ({ type: SET_LOGOUT }) // 초기값 설정 const initialState = { isLogin: false } // 홈으로 이동 함수 export const goToHome = (navigate) => () => { navigate(‘/’); } // 리듀서 만들기 export default function logincheck(state=initialState, action) { switch(action.type){ case SET_LOGIN: return { isLogin: true } case SET_LOGOUT: { return { isLogin: false } } default: return state; } }

util/cookie.js

import { Cookies } from ‘react-cookie’; const cookies = new Cookies(); // 쿠키 생성함수 export const setCookie = (name, value, options) => { return cookies.set(name, value, {…options}); } // 쿠키 접근함수 export const getCookie = (name) => { return cookies.get(name); } // 쿠키 삭제함수 export const removeCookie = (name) => { return cookies.remove(name) }

App.js

import ‘./App.css’; // import CustomerList from ‘./components/CustomerList’; import DetailCustomer from ‘./components/DetailCustomer’; import Footer from ‘./components/Footer’; import Header from ‘./components/Header’; import { Route, Routes } from “react-router-dom”; // import CreateCustomer from ‘./components/CreateCustomer’; import EditCustomer from ‘./components/EditCustomer’; import CustomerContainer from ‘./components/CustomerContainer’; import CreateCustomerContainer from ‘./components/CreateCustomerContainer’; import JoinForm from ‘./components/JoinForm’; import Login from ‘./components/Login’; // const customers = [ // { // no: 1, // name: “고객”, // phone: “01012345678”, // birth: “19920206”, // gender: “여성”, // add: “울산시 남구” // }, // { // no: 2, // name: “그린”, // phone: “01012345678”, // birth: “19920206”, // gender: “남성”, // add: “울산시 동구” // }, // { // no: 3, // name: “kh”, // phone: “01012345678”, // birth: “19920206”, // gender: “여성”, // add: “울산시 남구” // } // ] function App() { return (

{/* props로 위에 {customers}를 CustomerList로 전달 */} {/* } /> */} } /> } /> } /> {/* } /> */} } /> } /> } />

); } export default App;

index.js

import React from ‘react’; import ReactDOM from ‘react-dom/client’; import ‘./index.css’; import App from ‘./App’; import reportWebVitals from ‘./reportWebVitals’; import { BrowserRouter } from ‘react-router-dom’; import { applyMiddleware, legacy_createStore as createStore } from ‘redux’; import rootReducer from ‘./modules’; import { composeWithDevTools } from ‘redux-devtools-extension’; import thunk from ‘redux-thunk’; import { Provider } from ‘react-redux’; import { CookiesProvider } from ‘react-cookie’; const store = createStore(rootReducer, composeWithDevTools(applyMiddleware(thunk))); console.log(store.getState()); const root = ReactDOM.createRoot(document.getElementById(‘root’)); root.render( ); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals();

키워드에 대한 정보 리 액트 회원 가입

다음은 Bing에서 리 액트 회원 가입 주제에 대한 검색 결과입니다. 필요한 경우 더 읽을 수 있습니다.

이 기사는 인터넷의 다양한 출처에서 편집되었습니다. 이 기사가 유용했기를 바랍니다. 이 기사가 유용하다고 생각되면 공유하십시오. 매우 감사합니다!

사람들이 주제에 대해 자주 검색하는 키워드 13 회원가입 구현 axios post 이용한 가입 데이터 전송

  • 동영상
  • 공유
  • 카메라폰
  • 동영상폰
  • 무료
  • 올리기

13 #회원가입 #구현 # # #axios #post #이용한 #가입 #데이터 #전송


YouTube에서 리 액트 회원 가입 주제의 다른 동영상 보기

주제에 대한 기사를 시청해 주셔서 감사합니다 13 회원가입 구현 axios post 이용한 가입 데이터 전송 | 리 액트 회원 가입, 이 기사가 유용하다고 생각되면 공유하십시오, 매우 감사합니다.

See also  인체 크로키 모델 | 입문자를 위한 인체 크로키 방법 2479 투표 이 답변

Leave a Reply

Your email address will not be published. Required fields are marked *