본문 바로가기
프로그래밍/react

[220427] 코드의 분리

by 한코코 2022. 5. 4.

코드 분리

코드를 분리해 4월46일에 만든 로그인기능을 유지해보았다.

다른 컴포넌트처럼 import로 가져올 수 있고, export default로 내보낼 수 있다.

// 내보낼때
export default useForm

// 가져올때
import useForm from './useForm.jsx'

 

 

 

 

비동기 코드 넘기기

중간에 상태값이 바뀌어서 재실행될때 코드는 비동기적으로 움직인다.

올바르게 회원가입을 했을때 1초후에 가입한 정보를 띄우는 비동기적 코드를 작성해보았다.

// 강제적으로 비동기 코드를 작성
// submit을 클릭했을때 items를 최신상태로 바꾸기
const request = async (items) => {
    const result = await new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve(items)
        },1000)
    })
}

// useForm.jsx로 넘겨버리기
const Form = () => {
    const {
        userid,
        password,
        errors,
        submit,
        handleSubmit
    } = useForm({userid:'',password:''},aa)

 

 

 

 

비동기 코드 받기

그러면 내용을 받는 코드에서도 비동기로 가도록 이렇게 async를 붙여야하지만, 에러가 난다.

에러내용 : 콜백함수 안에 함수를 따로 선언해서 해라.

useEffect( async ()=>{} )

문제점 해결한 비동기 코드

useEffect( ()=>{ 
    // 함수생성
    const init = async () => {
        if(submit){
            if(Object.keys(errors).length === 0){
                onSubmit(values)
            }
            setSubmit(false)
        }
    }

    init() // 호출
    }, [errors]
)

 

 

 

 

최종코드

더보기
// Form.jsx
import React,{useState,useEffect} from 'react'
import validate from '../utils/validate.jsx'
import useForm from './useForm.jsx' 

// submit을 실행했을때 items의 최신형을 가져올 수 있음
const request = async (items) => {
    // 강제적 비동기
    const result = await new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve(items)
        },1000)
    })
    alert(JSON.stringify(result))
}

const Form = () => {
    const {
        userid,
        password,
        errors,
        submit,
        handleSubmit
    } = useForm({userid:'',password:''},request,validate)
    /*
        password:{value:'', onChange: f}
        userid:{value:'', onChange: f}
        errors:{},
        submit:boolean,
        handleSubmit:f()=>{}
    */

    return(
        <form onSubmit={handleSubmit}>
            <ul>
                <input type="text" name="userid" {...userid} className={errors.userid && 'error'}/>
                {errors.userid && <span>{errors.userid}</span>}
            </ul>
            <ul>
                <input type="text" name="password" {...password}/>
                {errors.password && <span>{errors.password}</span>}
            </ul>
            <ul>
                <input type="submit" value="회원가입" disabled={submit}/>
            </ul>
        </form>
    )
}

export default Form

 

// useForm.jsx
import React,{useState,useEffect} from 'react'

const useForm = (defaultValues,onSubmit,validate) => {
    const [values,setValues] = useState(defaultValues)
    const [submit,setSubmit] = useState(false)
    const [errors,setErrors] = useState({})

    const onChange = e => {
        const {name,value} = e.target
        setValues({...values,[name]:value})
    }

    const handleSubmit = e => {
        e.preventDefault()
        setSubmit(true)

        //values:{userid:'adsd', password:'afasdf'}
        setErrors(validate(values))
    }
    
    useEffect( ()=>{
        const init = async () => {
            if(submit){
                if(Object.keys(errors).length === 0){
                    onSubmit(values)
                }
                setSubmit(false)
            }
        }

        init()
        }, [errors]
    )

    return{
        ...Object.keys(defaultValues).reduce((acc,v)=>{
            acc[v] = {
                value:values[v],
                onChange
            }
            return acc
        },{}),
        handleSubmit,
        errors,
        submit
    }
}

export default useForm;

 

댓글