From 0c7181beba68cf6cdd095d43fb22eee94bc8569a Mon Sep 17 00:00:00 2001 From: saseungmin Date: Fri, 26 Feb 2021 16:15:01 +0900 Subject: [PATCH] [Refactoring] Auth input onChange - Refactoring onChange action of input using recoil selector --- src/components/auth/AuthInput.jsx | 14 ++-- src/components/auth/AuthInput.test.jsx | 69 -------------------- src/components/auth/AuthModalForm.jsx | 2 +- src/components/auth/AuthModalForm.test.jsx | 75 ++++++++++++++++++---- src/recoil/auth/index.js | 3 +- src/recoil/auth/withFields.js | 27 ++++++++ 6 files changed, 97 insertions(+), 93 deletions(-) delete mode 100644 src/components/auth/AuthInput.test.jsx create mode 100644 src/recoil/auth/withFields.js diff --git a/src/components/auth/AuthInput.jsx b/src/components/auth/AuthInput.jsx index 8d6b98d..e4e3aed 100644 --- a/src/components/auth/AuthInput.jsx +++ b/src/components/auth/AuthInput.jsx @@ -2,7 +2,7 @@ import React from 'react'; import { useRecoilState } from 'recoil'; -import authFieldsAtom from '../../recoil/auth'; +import { authWithFields } from '../../recoil/auth'; const authFieldsProperty = { userId: { @@ -23,20 +23,14 @@ const authFieldsProperty = { }; const AuthInput = ({ formType, inputName }) => { - const [authFieldsState, setAuthFieldsState] = useRecoilState(authFieldsAtom); + const [authFieldsState, setAuthFieldsState] = useRecoilState(authWithFields); const { inputType, placeholder, autoComplete } = authFieldsProperty[inputName]; const onChange = (e, type) => { const { name, value } = e.target; - setAuthFieldsState({ - ...authFieldsState, - [type]: { - ...authFieldsState[type], - [name]: value, - }, - }); + setAuthFieldsState({ name, type, value }); }; return ( @@ -45,7 +39,7 @@ const AuthInput = ({ formType, inputName }) => { name={inputName} placeholder={placeholder} autoComplete={autoComplete} - value={authFieldsState[formType][inputName]} + value={authFieldsState[inputName]} onChange={(e) => onChange(e, formType)} /> ); diff --git a/src/components/auth/AuthInput.test.jsx b/src/components/auth/AuthInput.test.jsx deleted file mode 100644 index a79f8e3..0000000 --- a/src/components/auth/AuthInput.test.jsx +++ /dev/null @@ -1,69 +0,0 @@ -import React from 'react'; - -import { RecoilRoot } from 'recoil'; - -import { render, fireEvent } from '@testing-library/react'; - -import InjectTestingRecoilState from '../common/InjectTestingRecoilState'; - -import AuthInput from './AuthInput'; - -describe('AuthInput', () => { - const renderAuthInput = ({ type, name, fields }) => render(( - - - - - - )); - - it('renders auth input', () => { - const props = { - type: 'login', - name: 'userId', - fields: { - login: { - userId: 'seungmin', - }, - }, - }; - - const { getByPlaceholderText } = renderAuthInput(props); - - const input = getByPlaceholderText('아이디'); - - expect(input).not.toBeNull(); - expect(input).toHaveValue('seungmin'); - }); - - it('listens event change input value', () => { - const props = { - type: 'login', - name: 'userId', - fields: { - login: { - userId: '', - }, - }, - }; - - const { getByPlaceholderText } = renderAuthInput(props); - - const input = getByPlaceholderText('아이디'); - - fireEvent.change(input, { - target: { - value: 'seungmin', - name: 'userId', - }, - }); - - expect(input).not.toBeNull(); - expect(input).toHaveValue('seungmin'); - }); -}); diff --git a/src/components/auth/AuthModalForm.jsx b/src/components/auth/AuthModalForm.jsx index c30274b..d8edbe0 100644 --- a/src/components/auth/AuthModalForm.jsx +++ b/src/components/auth/AuthModalForm.jsx @@ -5,8 +5,8 @@ import { useRecoilValue, useResetRecoilState } from 'recoil'; import styled from '@emotion/styled'; import { css } from '@emotion/react'; -import authFieldsAtom, { authStatusAtom } from '../../recoil/auth'; import { FORM_TYPE } from '../../utils/constants/constants'; +import authFieldsAtom, { authStatusAtom } from '../../recoil/auth'; import AuthInput from './AuthInput'; diff --git a/src/components/auth/AuthModalForm.test.jsx b/src/components/auth/AuthModalForm.test.jsx index 87f0418..a63c8f5 100644 --- a/src/components/auth/AuthModalForm.test.jsx +++ b/src/components/auth/AuthModalForm.test.jsx @@ -4,14 +4,27 @@ import { RecoilRoot } from 'recoil'; import { render, fireEvent } from '@testing-library/react'; -import AuthModalForm from './AuthModalForm'; import InjectTestingRecoilState from '../common/InjectTestingRecoilState'; +import AuthModalForm from './AuthModalForm'; + +const authFieldsState = { + register: { + userId: '', + password: '', + passwordConfirm: '', + }, + login: { + userId: '', + password: '', + }, +}; describe('AuthModalForm', () => { - const renderAuthForm = (auth) => render(( + const renderAuthForm = ({ auth, fields = authFieldsState }) => render(( @@ -21,8 +34,10 @@ describe('AuthModalForm', () => { context('When type login', () => { it('renders login form contents', () => { const props = { - type: 'login', - visible: true, + auth: { + type: 'login', + visible: true, + }, }; const { container } = renderAuthForm(props); @@ -34,8 +49,10 @@ describe('AuthModalForm', () => { context('When type register', () => { it('renders register form contents', () => { const props = { - type: 'register', - visible: true, + auth: { + type: 'register', + visible: true, + }, }; const { container, getByPlaceholderText } = renderAuthForm(props); @@ -47,8 +64,10 @@ describe('AuthModalForm', () => { it('When click Submit button, listen event', () => { const props = { - type: 'register', - visible: true, + auth: { + type: 'register', + visible: true, + }, }; const { getByTestId } = renderAuthForm(props); @@ -58,8 +77,10 @@ describe('AuthModalForm', () => { it('When click Close button, the modal window is closed.', () => { const props = { - type: 'register', - visible: true, + auth: { + type: 'register', + visible: true, + }, }; const { container, getByText } = renderAuthForm(props); @@ -68,13 +89,43 @@ describe('AuthModalForm', () => { expect(container).toBeEmptyDOMElement(); }); + + it('listens event change input value', () => { + const props = { + auth: { + type: 'login', + visible: true, + }, + fields: { + login: { + userId: '', + }, + }, + }; + + const { getByPlaceholderText } = renderAuthForm(props); + + const input = getByPlaceholderText('아이디'); + + fireEvent.change(input, { + target: { + value: 'seungmin', + name: 'userId', + }, + }); + + expect(input).not.toBeNull(); + expect(input).toHaveValue('seungmin'); + }); }); context("Isn't visible", () => { it('nothing renders', () => { const props = { - type: 'login', - visible: false, + auth: { + type: 'login', + visible: false, + }, }; const { container } = renderAuthForm(props); diff --git a/src/recoil/auth/index.js b/src/recoil/auth/index.js index ee5a92e..97eaf54 100644 --- a/src/recoil/auth/index.js +++ b/src/recoil/auth/index.js @@ -1,5 +1,6 @@ import authFieldsAtom, { authStatusAtom } from './atom'; +import authWithFields from './withFields'; -export { authStatusAtom }; +export { authStatusAtom, authWithFields }; export default authFieldsAtom; diff --git a/src/recoil/auth/withFields.js b/src/recoil/auth/withFields.js new file mode 100644 index 0000000..a7a19fa --- /dev/null +++ b/src/recoil/auth/withFields.js @@ -0,0 +1,27 @@ +import { selector } from 'recoil'; + +import authFieldsAtom, { authStatusAtom } from './atom'; + +const authWithFields = selector({ + key: 'authWithFields', + get: ({ get }) => { + const { type } = get(authStatusAtom); + const authFields = get(authFieldsAtom); + + return authFields[type]; + }, + set: ({ set }, { name, value, type }) => { + set( + authFieldsAtom, + (prevState) => ({ + ...prevState, + [type]: { + ...prevState[type], + [name]: value, + }, + }), + ); + }, +}); + +export default authWithFields;