React 기초 정리 4)

Jinmin Kim·2021년 7월 3일
0

JSX의 for과 if

JSX안에서는 for와 if를 사용할수있지만 너무 코드가 더럽게나와서 잘 사용하지 않는다.

삼항연산자 -> JSX의 if절

    this.state.result.length !== 0 ? null : <div>평균 시간 : {this.state.result.reduce((a, c) => a + c) / this.state.result.length}ms</div>

ref의 또다른 사용

useState와 useRef와 또다른 차이점**
state를 변경하면 render가 자동으로 실행되는데, useRef를 사용하면 실행되지않는다.(화면에는 영향을 미치게하고 싶지않을때)
this를 대신해서 useRef를 사용하게된다. 화면은 바꾸고싶지않은데 바꾸게 되는값들을 이것으로 사용해서 넣어준다.

  • useRef의 다른 사용 방법
    const timeout = useRef(null);
    const startTime = useRef();
    const endTime = useRef();

if, for 사용

즉시 실행 함수를 사용해줘야하고, 거의는 사용하지 않는다.
사용해야할떄가 있긴하지만 아주 적은 빈도

  • if
{{(() =>{
                if(result.length === 0){
                    return null;
                } else{
                    return <>
                        <div>평균 시간 : {result.reduce((a,c) => a + c) / result.length}ms</div>
                        <button onClick={onReset}></button>
                    </>
                }
            })()}}
  • for
{/* {(() => {
            const array = [];
            for (let i =0 ; i < tries.length; i++){
              array.push(<Try key={`${i+ 1}차 시도 :  ${v.try} `} tryInfo={v}/>);
            }
            return array;
          })()} */}

리액트 라이프사이클

Class의 라이프사이클

첫번째 랜더링 : 클래스의 경우 -> constructor -> render -> ref -> componentDidMount
[(setState/props) 바뀔때 : shouldComponentUpdate(true) -> render -> componentDidUpdate]
소멸할때 componentWillUnmount -> 소멸

    //render가 성공적으로 실행됬다면, componentDidMount이 실행되게된다.
    componentDidMount(){ //컴포넌트가 첫 렌더링한 후 -> 비동기 요청을 많이하게된다

    }

    componentDidUpdate(){ // Rerendering이 될때

    }

    componentWillUnmount(){ //컴포넌트 제거되기 직전 -> 비동기 요청을 정리를 많이하게된다.

    }

Hooks의 라이프사이클 따라하기

Hooks에는 라이프사이클이라는것은 따로 없지만 비슷하게 사용할수있는 기능이 제공된다.

userEffect

    useEffect(() => { // componentDidMount, componentDidUpdate 역할을 한다(두개를 합쳐놨다라고 생각한다)
            return () => { // componentWillUnMount의 역활을 한다

            }
        }, []);

Hooks를 사용할때는 render가 될때마다 Hooks안에 있는 함수 컴포넌트 전체가 다시 실행된다.

아래의 코드를 돌리게되면 imgCoord는 0.1초마다 계속 바뀌게 되는데 두번째 인수 배열의 넣은값이 바뀔때에
useEffect가 실행되기 때문에 아래의 console.log을 찍었을때에는
다시실행
종료
가 log로 찍히게된다.

useEffect(() => { // componentDidMount, componentDidUpdate 역할을 한다(두개를 합쳐놨다라고 생각한다)
        console.log("다시 실행")
        interval.current = setInterval(changeHand, 100);
        return () => { // componentWillUnMount의 역활을 한다
            console.log("종료")
            clearInterval(interval.current)
        }
    }, [imgCoord]);// 두번째 인수 배열에 넣은값(imgCoord)들이 바뀔때 useEffect가 실행된다.
    }, []); //처음에만 한번 실행되고 그다음부터는 실행하지 않겠다는것을 의미한다.

아래와 같은 방법은 꼼수!

  • componentDidMount만
  useEffct(() => {

    }, [])
  • componentDidUpdate만
    Hooks에서 componentDidMount는 어쩔수없이 실행이되어야하기때문에 그때는 아무것도 실행이 안되게 만들어주고
    componentDidUpdate에서만 실행될수있도록 만들면 된다
      const mounted = useRef(false);
      useEffect(() => {
          if(!mounted.current){ //componentDidMount의 실행
              mounted.current = true;
          }
          else{ //compoenntDidUpdate의 실행
          //내가 원하는 로직
          }
      }, [바뀌는값])

useMemo

//useMemo 사용, 두번째 인자가 변경되면 callback함수가 실행되게된다.
//useMemo : 복잡한 함수 결괏값을 기억(hooks는 함수컴포넌트 전체가 재실행되는데 이러한 비효율적인 부분을 대비해서 값을 기억해두면 훨신 효율적)
//useRef : 일반 값을 기억

    useMemo(() => callback, []);

useCallback

//useCallback : useMemo는 return 값을 기억하는것인데, useCallback은 함수 자체를 기억하는방법
//useCallback 함수 자체를 기억해두어서 hooks의 함수컴포넌트가 모두 재실행된다 할지라도, 함수를 기억해서 그 함수를 다시 만들어주지 않아도된다.
//단점은 state를 이전의 처음것을 기억한다.
//state를 내부에서 사용하기위해서는 두번째 인자에 값을 넣어줘야 변경되었을때 새로운 데이터를 가져올수가 있다.

//자식 컴포넌트에 props 함수로 전달해줄때는 useCallback을 꼭 사용하여서 전달하여야한다.

    useCallback(() => callback, [])

    const onClickRedo = useCallback(() => {
        console.log(winNumbers);
        setWinNumbers(getWinNumbers());
        setWinBalls([]);
        setBonus(null);
        setRedo(false);
        timeouts.current = [];
  }, [winNumbers]);

  {bonus && <Ball number={bonus} onClick={onClickRedo} />}

Hooks의 Tip!

1.hooks는 선언주거나 실행해주는 순서가 생각보다 중요하다. 2.조건문안에 hooks를 넣으면안되며, 함수나 반복문안에도 어지간해서는 넣지않는게 좋다.
3.useEffect, useCallback 같은것안에서 usestate를 사용해서는 안된다. 4. { useState, useRef, useEffect, useMemo, useCallback } 5가지는 기본이니까 확실하게 알자
5.useEffect는 한번뿐만아니라 여러번 사용할수있다는것을 기억하자.


useReducer 사용

// initialState state와 같은 역활을 하는 useReducer
    const initialState = {
        winner: '',
        turn: 'O',
        tableData: [
            ['', '', ''],
            ['', '', ''],
            ['', '', ''],
        ],
        recentCell: [-1, -1],
    };

    // reducer를 사용해서 initialState(state)의 데이터를 변경한다
    const reducer = (state, action) => {
        //action은 reducer의 {type: SET_WINNER, winner: 'O'}를 뜻한다.
        switch (action.type) {
            case SET_WINNER:
            //state.winner = action.winner; 이렇게 하면안된다.

            return {
                ...state,
                winner: action.winner,
            };
        }
    };

    // Reducer 선언해주기(함수안에)
    const [state, dispatch] = useReducer(reducer, initialState);

    // dispatch로 reducer에 전달하기
    dispatch({ type: SET_WINNER, winner: turn });

state는 아무도 못건들고 action이 state를 수정할수있는데, 그것을 dispatch로 알린다.
어떻게 바꿀지는 reducer에서 정해둔다.

//state는 비동기라는 사실!! 비동기 State에 따라 어떤것을 처리할때는 useEffect를 사용한다.
//Redux는 동기적으로 State를 변경해주는데, userReducer는 비동기적으로 state를 변경한다.

성능 최적화를 memo를 하고나서 이후에도 최적화를 더해보고싶을때
useMemo로 컴포넌트를 기억해버리는 방법을 시도해볼수도있다.

useMemo(
  () => (
    <Td
      key={i}
      rowIndex={rowIndex}
      cellIndex={i}
      cellData={rowData[i]}
      dispatch={dispatch}
    >
      {''}
    </Td>
  ),
  [rowData[i]],
),
profile
Let's do it developer

0개의 댓글