[rust+react] 4. React tutorial / 2

성욱김·2022년 2월 13일
0

1. Props

props란 무엇인가.
부모 Component에서 자식 Component로 데이터를 보내는 방법이다.

안되는게 당연하지만 , App Component의 State를 ConverterApp 들에서는 사용할 수없다.
아마 이런걸 가능하게 해준다는 것 같다.

1.1 Props의 사용

음.. 비슷했지만 조금은 다르다.

 function Btn({x , y }){
            return <button style={{
                backgroundColor: "Tomato",
                color:"white",
                padding:"10px 20px",
                border:0,
                borderRadius:10,
            }}> {x ? x : y} </button>;
}

component에 인자를 입력해줄 수 있다.

<Btn text="Save Changes" x="2" />
<Btn text="Confirm" y = "4"/> 

넘겨주는 인자에는 제한이 없지만 ,
props를 받아 props.x props.y로 사용하던가

내가 작성한 방법처럼 {x , y , text}로 받아야 한다.

여기서 내가 작성한 코드는 x가 있으면 x , x가 없으면 y를 print하는 버튼인데


잘 작동한다.

코드를 따라서 쳐보는 것도 물론 향상에 도움이 되지만 살짝 비틀어서 이런걸 시도해보는게 훨씬 머리에 잘 남는 것 같다.

1.2 Props 인자의 한계는?

어떤 것까지 보낼 수 있는지 알아보자.
예상으로는 뭐 Component를 보낸다던가 State를 보낸다던가 하는것도 가능하지 않을까?

<Btn text={value} x="2" onClick={changeValue}/> 

위와 같이 작성하면 뭔가 onClick 이벤트리스너가 생성된것처럼 착각을 불러일으킨다.
하지만 실제로 변하는건 아무도 없고 단지 prop을 Btn에 전달하는 것에 불과하다.
따라서 component로 돌아가

function Btn({onClick,text,x , y }){
            return <button style={{
                backgroundColor: "Tomato",
                color:"white",
                padding:"10px 20px",
                border:0,
                borderRadius:10,
                }}
            onClick ={onClick}
            > {text} </button>;
        }

이곳에서 eventListener를 설정한다.

1.3 React.memo()

function App() {
            const [value, setValue] = React.useState("Save Changes");
            const changeValue = () => setValue("Revert Changes");
            return(
                <div>
                    <Btn text={value} x="2" onClick={changeValue}/> 
                    <Btn text="Confirm" y = "4"/> 
                </div>
            );
}

작성한 코드는 첫번째 버튼의 props만 변경하게 된다. 하지만 React의 규칙에 의해 브라우저는 App안에 있는 모든 것들을 다시 렌더링하게 되는데 이는 비효율적이다.

따라서 Prop이 변경되지 않는한 다시 Rendering 하지 않는 기능은 최적화에 도움을 줄텐데,
React.memo()라는 기능을 사용하면 된다.

const MemorizedBtn = React.memo(Btn)
        function App() {
            const [value, setValue] = React.useState("Save Changes");
            const changeValue = () => setValue("Revert Changes");
            return(
                <div>
                    <MemorizedBtn text={value} x="2" onClick={changeValue}/> 
                    <MemorizedBtn text="Confirm" y = "4"/> 
                </div>
            );
        }

간단한 수정 만으로 브라우저는 이제 두번째 Confirm text를 갖는 component는 다시 렌더링하지 않게 된다.

1.4 Prop Types

협업을 할 때 , 사소한 실수를 방지할 수 있는 기능이다.

MemorizedBtn.propTypes = {
            text: PropTypes.string,
            x: PropTypes.number,
            y: PropTypes.number,
        }

이 설정은 MemorizedBtn의 prop들에 대한 type을 강제하는 것으로
잘못 작성할 경우 아래와 같은 경고를 보여준다.

y = "4"는 숫자가 아니라 문자를 넘겼다.
propType은 이럴 때 경고를 보여주고
y = {4} 로 변경하기 전까지는 사라지지 않는다.

2. create-react-app

2.1 nodejs

cra를 사용하기 위해서는 우선 nodejs를 설치해야한다.

node.js는 백엔드로 알고 있는데 일단은 설치해보자.
오래걸린다 . . .

npm start를 통해 개발용 서버를 구축했고,
이것을 나중에 rust단으로 바꾸는게 최종 목표다.

2.2 독립적인 코딩 및 css

style 을 적용할 때 .module.css 라는 파일을 통해 진행하는데 이게 참 편리하다.

App.js에 사용되는 style을 위해 App.module.css 라는 파일을 만들고 ,
단순히 클래스를 만드는 것 만으로 style을 적용할 수 있다.

App.module.css

.title {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
    font-size: 18px;
    color:blueviolet;
}

App.js

import styles from "./App.module.css";
function App() {
  return (
    <div>
      <h1 className={styles.title}>
        Welcome Back!!
      </h1>
      <Button text="Hello React"/>
    </div>
  );
}

2.3 Effect

React 의 핵심인 반응형 앱을 위한 Effect가 아닐까?

가장 중요하다고 하니 좀만 쉬었다가 해야겠다.

2.3.1 한번만 실행되는 코드

버튼의 onClick 이벤트리스너와 연결되는 함수를 작성하면 , 그 내용이 무엇이든 render될때마다 같이 실행된다.

예를 들면

const onClick = () => setValue((prev) => prev+1);
console.log("Hi , I'm rendered);
 

위 코드는 버튼이 눌릴때마다 rendering 되며 , console.log를 실행한다.
하지만 어떤 경우에는 처음 rendering 될때만 인사를 하고 싶을 수도 있다.

const onClick = () => setValue((prev) => prev+1);
???(console.log("Hello , I'm rendered in first));
  

이런 경우에 대해 알아보자.
(물론 다른 state를 하나 더 만들어서 조건문을 사용하면 매우 쉽다)

console.log("I run all the time");
useEffect(()=>console.log("I run only once"),[]);

바로 useEffect 함수이다.

이 함수 안에 첫번째 인자로 들어가는 함수는 state가 변하더라도 다시 실행되지않는다.

한번만 실행된다.

2.3.2 Deps

Effect는 반응형 보다는 useEffect 함수에 대한 것이었다.
아무튼 두번째 인자로 들어가는 Deps란 무엇인지 알아보자.

useEffect(()=>{
    console.log("searching for", keyword);
  },[keyword]);

두 번째 인자는 추적할 state였다. 위 코드는 keyword가 변할 때만 console.log를 실행한다.

위에서 적은 코드는 추적할 state가 없었기 때문에 ( 빈 array ) 딱 한번만 실행되는 것이다.

2.3.3 연습

App.js

function App() {
  const [counter, setValue] = useState(0);
  const [keyword, setKeyword] = useState("");
  const onClick = () => setValue((prev) => prev+1);
  const onChange = (event) => setKeyword(event.target.value);
  console.log("I run all the time");

  useEffect(()=>console.log("I run only once"),[]);

  useEffect(()=>{
    console.log("searching for", keyword);
  },[keyword]);
  return (
    <div>
      <input 
        value={keyword} 
        onChange={onChange} 
        type="text" 
        placeholder="Search here . . ."/>
      <h1 className={styles.title}>
        {counter}
      </h1>
      <Button onClick={onClick} state={counter} text="Click me"/>
    </div>
  );
}

Button.js

function Button({text , onClick , state}){
    useEffect(()=>console.log("The thing i chase is ",state) , [state])
    return <button onClick={onClick} className={styles.btn}>{text}</button>;
}
  1. App.js에서 Button에 state인자를 통해 counter를 넘겨준다.
  2. Button.js에서 Button component는 state인자를 받아서 변하는지 추적한 후 출력한다.



의도한 대로 잘 실행된다.

부모의 state를 자식 component가 넘겨받기만 한다면 추적할 수 있는 것이다.

Why react again

react는 최소단위의 render를 할 수 있기 때문에 좋다고 했다.
하지만 이번 장에서 배운 effect기능을 사용하지 않는다면 그 원칙을 위배하게 된다.
다른 기능을 하는 버튼을 누르는데 검색창의 input을 추적해야 할 이유는 당연히 없다.

적절한 useEffect를 사용해서 필요한 부분만 다시 실행할 수 있는 코드를 작성하자.

0개의 댓글