Fullstack-Study-241204-250625

커리큘럼(12-30/변경)

01. Java
02. git
03. Database 
04. Jsp [Server]

05. HTML,CSS 
07. JS
06. 미니프로젝트-2W

08. SpringFramework , SrpingBoot 
19. 중간프로젝트 (1M)
10. Linux 명령어
11. AWS
12. Docker
13. Kubernetes
14. React JS (v)
15. App - Android
16. 최종프로젝트 (1M)

React(리액트)

리액트 훅

useRef()

const 사용할이름 = useRef(초기값)

function HookQ(){


    /* 
    1. 이 페이지가 mount된 이후에 useEffect사용해서 id태그에 포커싱을 하나 넣기
    2. id, pw는 동시에 state로 관리
    3. 로그인 클릭시 두값중 한개라도 공백이라면, 공백인 태그에 포커싱 추가
    4. 로그인 클릭시 공백이 아니라면, 경고창으로 id, pw출력
    */

    const [info,setInfo] = useState({id:'',pw:''});
    const idRef=useRef(null);
    const pwRef=useRef(null);

    const handleClick = (e) => {
        if(idRef.current.value===''){
            idRef.current.focus();
        }
        else if( pwRef.current.value===''){
            pwRef.current.focus();
        }
        else{
            alert(`id=${idRef.current.value} , pw=${pwRef.current.value}`)
        }
    };

    useEffect(()=>{
        idRef.current.focus();
    },[])


    return(

        <>
            <div>
                <input type="text" name="id" onChange={e=>setInfo({...info,id:e.target.value})} value={info.id} placeholder="아이디" ref={idRef}   /><br/>
                <input type="password" name="pw" onChange={e=>setInfo({...info,pw:e.target.value})} value={info.pw}placeholder="비밀번호" ref={pwRef} /><br/>
                <button type="button" onClick={handleClick}>로그인</button>
            </div>  
        </>
    )
}

useReducer()

const [현재값, 리듀서action함수] = useReducer(리듀서함수명, state값);

export const firstReducer = (state,action) =>{

    // state,action을 이용해서 state값 변경
    // state는 직접 값을 변경하는 작업을 피해서 수정
    // 초기 state유형 = {value:0}
    if(action.type==='up'){
        state = {value:state.value+1}
    }else if(action.type=='down'){
        state = {value:state.value-1}
    }else if(action.type== 'result')    {
        state={value:0}
    };
}



function HookReducer(){


    // const [현재스테이트값, 리듀서를 변경하는 acion함수] = useReducer(리더서함수, state초기값)

    const [state, some] = useReducer(firstReducer,{value:0});

    const up = ()=>{
        some({type:"up"}); // {type:"up"}은 리듀서의 두번째 매개변수로 전달달
    }
    return(
        <>
            <h3>useReducer훅</h3>    

            현재state값: {state.value}
            <button type="button" onClick={up}>증가</button>
            <button type="button" onClick={()=>some({type:"down"})}>감소</button>
            <button type="button" onClick={()=>some({type:"reset"})}>초기화</button>
        </>
    )
}
  • some함수안에 객체형태로 데이터를 담아서 보내게 되면 firstReducer의 action에서 그 값을 받음
  • 즉 **dispatch함수**는 객체 형태의 액션을 reducer에 전달하는 역할 수행
  • state의 구조reducer를 호출하는 컴포넌트에서 명시

const [state, some] = useReducer(firstReducer,{value:0});부분

useMemo

function HookMemo(){

    const [num,setNum] = useState(0);
    const [text,setText] = useState('');

    // const calc=(()=>{

    //     // 계산이 오래걸리는 예시 함수
    //     console.log("계산시작")
    //     let i=0;
    //     while(i<=1000000000)i++;
    //     console.log("계산완료");

    //     return num % 2 == 0 ? "짝수":"홀수";

    // })();

    const calc = useMemo( () => {
        // 계산이 오래걸리는 예시 함수
        console.log("계산시작")
        let i=0;
        while(i<=1000000000)i++;
        console.log("계산완료");

        return num % 2 == 0 ? "짝수":"홀수";
    },[num]) // num이 변경될때만 실행

    return(
        <>
            <h1>useMemo훅</h1>

            <input type="number" onChange={(e)=>setNum(e.target.value)} value={num}/>
            <br/>
            결과:{calc}


            <br/>
            <input type="text" onChange={e=>setText(e.target.value)} value={text}/>
        </>
    )
}
  • 특정 state를 지정하고 해당 state의 값이 변화할때만 useMemo안의 함수 실행
  • 현재, num값이 바뀔시 useMemo안의 함수 실행

useCallback

const memoizedCallback = useCallback(() => {
  // 실행할 함수 내용
}, [의존성]);
  • () => {...} : 기억할 함수
  • [의존성] : 배열 안 값이 바뀌지 않으면, 기억한 함수를 그대로 사용함
function HookCallback() {

    const [count, setCount] = useState(0);

    const increase = () => {
        setCount( prev => prev + 1);
    }

    return (
        <> 
            <h3>useCallback훅</h3>
            <button type="button" onClick={increase}>버튼</button>
            <br/>
            현재값: {count}


            <Child increase={increase}/>
        </>
    )
}

//자식컴포넌트
const Child = ({increase}) => {
    //자식 컴포넌트에서 상위 컴포넌트의 state값을 변경

    console.log("부모에서 클릭하던, 자식에서 클릭하던 렌더링이 일어남");
    return (
        <>
            <h3>자식 컴포넌트</h3>        
            <button type="button" onClick={()=>increase()}>증가</button>
        </>
    )
}
  • 부모 HookCallback컴포넌트에서 만든 increase함수를 Child컴포넌트에 전달해줌
  • **useCallback**함수를 쓰지 않으면 Child컴포넌트의 증가버튼을 누르게 되면 count state값이 증가하게 되면서 리렌더링 되며 부모컴포넌트의 increase함수가 재생성
  • increase함수안에서 prev=>prev+1로 쓴이유는 setCount(count+1)로 설정하게 되면 제일 처음 받았던 count가 0인데 이 count에 대해서 계속 +1을 하기때문에 increase함수 호출시 계속 0+1인 1로 count가 설정됨
  • **useCallback**함수를 써서 Child컴포넌트에서 증가버튼을 눌러 리렌더링시켜도 처음 부모 컴포넌트에서 생성한 increase함수를 재사용

React 스타일링

  1. 태그에 직접 지정

<p style=>CSS파일로 디자인하기</p>

  1. 일반 CSS파일로 적용

import "./css/App.css"

  1. css모듈로 적용
import myStyle from "./css/App.module.css";

function App(){
    return(
        <>
            <Fragment>
                <section className={myStyle.appWrap}>
                    <div className="title">hello world</div>
                </section>
            </Fragment>
        </>
    )
}
.appWrap{
    background-color:pink;
    display:flex;
    justify-content: center;
    align-items: center;
    height:100vh;
}


/* .tilte이라는 이름으로 바로 사용가능 */
:global .title{
    color: red;
}
>> ```
  1. public폴더에 css디자인

React 라우터

SPA(Single Page Application)

라우팅

라우터 적용하기

  1. 라우터를 사용할때는 index.js에서 App컴포넌트를 로 감싸줌
  2. 페이지 컴포넌트 만들기
  3. App컴포넌트에서 를 사용해서 분기
  4. 주소요청을 통해 확인
import { BrowserRouter } from "react-router-dom";
....
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>

);
function App() {

  return (
    <Routes>
        <Route path='/' element={<Home/>}/>
        <Route path='/user' element={<User/>}/>
        <Route path='/info' element={<Info/>}/>
    </Routes>
  );
}
  • /요청은 Home컴포넌트
  • /user요청은 User컴포넌트
  • /info요청은 Info컴포넌트