react

react

September 11, 2020 ( last updated : September 10, 2020 )
styled Component useState useReducer useContext

https://github.com/gmm117/gmm117.github.io


Abstract

    Syled Components, useState, useReducer, useContext
    리액트 성능개선
        리액트 렌더러를 최적화
        

리액트 성능개선

리액트 성능느려지는 원인

리액트 성능개선 코드

shouldComponentUpdate

shouldComponentUpdate(nextProps, nextState, nextContext){
	if(this.state.conuter !== nextState.counter 
 counter { //미래의
    	return true
    }
    
    return false;
}

pureComponent

class BlahBlah extends PureComponent {

}

React.memo

const Try = memo(() => {})

참조타입 render밖에 선언하기

return (
 <>
  	<Title>{title is..}</Title> // {}
	  <ShowPost postClick={()=>{console.log('click handler')}} /> // () => {}
 </>
)

children 컴포넌트 갯수를 동일하게 유지하기

<div>
    <Header />
    { state.isToggle && <Subheader /> }
    <Content />
</div>

useEffect 매번 실행되지 않게 하기

useEffect(() => {
  document.title = `You clicked ${count} times`;
}, [count]);

React.memo : 컴포넌트 렌더링 결과 재사용

useCallback : 함수 캐시

React.memo, UseCallback을 활용한 시나리오

useMemo : 연산 결과 캐시

Profiling : 렌더링 최적화 확인

참고사이트

https://velog.io/@lllen/react-%EC%84%B1%EB%8A%A5-%EA%B0%9C%EC%84%A0#react-%EB%A0%8C%EB%8D%94%EB%A7%81-%EC%B5%9C%EC%A0%81%ED%99%94-8%EA%B0%80%EC%A7%80

리액트 렌더러를 최적화

// 최적화 전
// 상태값이 변경되서 렌더링 할 시 JSX 얻기위해 Logger 새로운 props 변경 후 컴포넌트 호출됨

// codesandbox: https://codesandbox.io/s/react-codesandbox-g9mt5

import React from "react";
import ReactDOM from "react-dom";

function Logger(props) {
  console.log(`${props.label} rendered`);
  return null; // 여기서 반환되는 값은 부적절하다...
}

function Counter() {
  const [count, setCount] = React.useState(0);
  const increment = () => setCount(c => c + 1);
  return (
    <div>
      <button onClick={increment}>The count is {count}</button>
      <Logger label="counter" />
    </div>
  );
}

ReactDOM.render(<Counter />, document.getElementById("root"));
// 최적화 후
// Counter props가 변경되지 않기 때문에 Logger의 컴포넌트가 호출되지 않도록 최적화됨

// codesandbox: https://codesandbox.io/s/react-codesandbox-o9e9f

import React from "react";
import ReactDOM from "react-dom";

function Logger(props) {
  console.log(`${props.label} rendered`);
  return null; // 여기서 반환되는 값은 부적절하다...
}

function Counter(props) {
  const [count, setCount] = React.useState(0);
  const increment = () => setCount(c => c + 1);
  return (
    <div>
      <button onClick={increment}>The count is {count}</button>
      {props.logger}
    </div>
  );
}

ReactDOM.render(
  <Counter logger={<Logger label="counter" />} />,
  document.getElementById("root")
);

참고사이트

https://ui.toast.com/weekly-pick/ko_20190725/

useState, useReducer, useContext 비교

숫자를 +1,-1 증감시키는 간단한 예제로 비교

// useState
/* useState hook을 이용하여서 state를 input에 바인딩하고 구조분해할당을 통해서 받은 set함수를 통해서 각 버튼의 클릭이벤트에 연결해서 counter값을 증감한다.  */
import React, { useState } from 'react';

function Counter() {
    let [count, setCount] = useState(0);

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

    const decrease = () => {
        setCount(prev => prev - 1);
    }

    return (
        <>
            <input value={count} />
            <button onClick={increase}>+</button>
            <button onClick={decrease}>-</button>
        </>
    );
}

export default Counter;
// useReducer
/* useReducer hook을 이용하여서 reducer에서 상태와 action의 타입을 통해서 state값을 세팅관리한다. 사용하는 로직에서는 useReducer에서 구조분해할당 함수인 dispatch를 호출해서 리듀서를 호출해서 상태를 변경하도록 한다.  */
import React, { useReducer } from 'react';

function reducer(state, action) {

    switch(action.type) {
        case 'INCREASE':
            return state + 1;
        case 'DECREASE':
            return state - 1;
        default:
            return state;
    }

    return null;
}

function Counter() {
    let [count, dispatch] = useReducer(reducer, 0);

    return (
        <>
            <input value={count} />
            <button onClick={() => dispatch({type : 'INCREASE'})}>+</button>
            <button onClick={() => dispatch({type : 'DECREASE'})}>-</button>
        </>
    );
}

export default Counter;
// createContext, useContext
/* Counter 부모컴포넌트에서 dispatch를 context를 통해서  ChildCounter에 전달하고 자식은 부모에 전달받은 context를 useContext hook을 통해서 받아서 dispatch를 호출함.*/

import React, { useReducer, useContext, createContext } from 'react';

const CounterDispatch = createContext();

function reducer(state, action) {

    switch(action.type) {
        case 'INCREASE':
            return state + 1;
        case 'DECREASE':
            return state - 1;
        default:
            return state;
    }

    return null;
}

function ChildCounter() {
    const dispatch = useContext(CounterDispatch);
    return (
        <>
            <button onClick={() => dispatch({type : 'INCREASE'})}>+</button>
            <button onClick={() => dispatch({type : 'DECREASE'})}>-</button>
        </>
    )
}

function Counter() {
    let [count, dispatch] = useReducer(reducer, 0);

    return (
        <CounterDispatch.Provider value={dispatch}>
            <>
                <input value={count} />
                <ChildCounter />
            </>
        </CounterDispatch.Provider>
    );
}

export default Counter;

Syled Components

const styled = (newElement) => {
	const el = document.createElement(newElement);
	return (args) => {
      el.style= args[0];
      console.log(args[0]);
      return el;
    }
};

var element = styled('h1')`
	border-radius : 10px;
	color:blue;
`;
console.log(element);

Originally published September 11, 2020
Latest update September 10, 2020

Related posts :