Modern React-Basic-작성중

Min·2021년 1월 26일
0

REACT

목록 보기
16/18
post-thumbnail

벨로퍼트와 함께하는 모던 리액트

벨로퍼트님의 함께하는 모던 리액트 내용을 학습하며 정리한 내용입니다.

1. 리액트의 등장배경

1) 자바스크립트

특정 값이 바뀌면 특정 DOM의 속성이 바뀌도록 연결을 해주어,
업데이트 하는 작업을 간소화 해주는 방식

2) 리액트

메모리상에 가상으로 존재하는 자바스크립트의 객체인 Virtual DOM을 이용하여,
상태가 업데이트 될때 실제 DOM과 비교후
필요한 곳의 UI만 렌더링 한다.

JSX

컴포넌트에서 XML 형식의 값을 반환해 줄 수 있다.
babel이 JSX를 자바스크립트로 변환해 준다.

Babel

JSX를 비롯한 새로운 자바스크립트 문법들을 사용하기 위해서

Webpack

JSX 문법으로 작성된 여러개의 컴포넌트를 한개로 결합하기 위해서

ReactDDOM.render

브라우저에 있는 실제 DOM 내부에 리액트 컴포넌트를 렌더링

2) JSX의 기본규칙

1. 태그는 꼭 닫혀있어야 한다.

function App() {
  return (
    <div>
      <Hello />
    </div>
  );
}

2. 두 가지 이상의 태그는 무조건 하나의 태그로 감싸져야한다.
Fragment는 브라우저 상에서 별도의 엘리먼트로 나타나지 않는다.

function App() {
  return (
    <>
      <Hello />
      <div>태그 2!</div>
    </>
  );
}

3. JSX 내부에서 자바스크립트 변수를 보여줘야 할 때는 {} 사용.
style과 className

function App() {
  const name = 'react';
  const style = { color: 'aqua' }
  return (
    <>
      <div style={style} className="클래스이름">{name}</div>
    </>
  );
}

4. 주석 : {/* 이렇게! */}
열리는 태그에서는 // 이렇게!

3. props

properties

어떤 값을 컴포넌트에게 전달해줘야 할때 사용되며
객체 형태로 전달

props 조회

1) 일반

return <div> {props.name} </div>

2) 비구조화할당

function Hello({ name }) {};

deafultProps

props를 지정하지 않았을 땐 기본적으로 사용할 값을
deafultProps로 설정.

props.children

컴포넌트 태그 사이에 넣은 값을 조회할 때

function App() {
  return (
    <Wrapper>
      <Hello name="react" color="red"/>
      <Hello color="pink"/>
    </Wrapper>
  );
}

function Hello({ color, name }) {
  return <div style={{ color }}> {name} </div>
}

Hello.defaultProps = {
  name: '이름없음'
}


function Wrapper({ children }) {
  return (
    <div>
      {children}
    </div>
  )
}

4. 조건부 렌더링

특정 조건에 따라 다른 결과물을 렌더링

1) 삼항 연산자

2) && 연산자

3) props 값을 생략하면 {true}

function App() {
  return (
    <>
      <Hello isSpecial />
    </>
  );
}

function Hello({ isSpecial }) {
  return (
    <>
      {isSpecial ? true일때! : false일때!}
      {isSpecial && false일때!}
    </>
  );
}

5. input 상태 관리

onChange() 이벤트 객체 e를 파라미터로 받아와서 사용 할 수 있는데,
이 객체의 e.target은 이벤트가 발생한 DOM 인 input DOM 을 가르키 된다.
이 DOM 의 value 값, 즉 e.target.value 를 조회하면
현재 input 에 입력한 값이 무엇인지 알 수 있다.

input의 상태를 관리할 때에는
input 태그의 value 값도 설정해주는 것이 중요하다.
그래야 상태가 바뀌었을때 input 의 내용도 업데이트 된다.

input에 name을 설정하고 이벤트가 발생했을 때 이 값을 참조하는 것이다.
useState 에서는 문자열이 아니라 객체 형태의 상태를 관리해주어야 한다.

리액트 상태에서 객체를 수정해야 할 때에는,
inputs[name] = value;
이런식으로 직접 수정하면 안된다.

새로운 객체를 만들어서 새로운 객체에 변화를 주고,
이를 상태로 사용해주어야 한다.

setInputs({
  ...inputs,
  [name]: value
});

불변성을 지켜주어야만 컴포넌트 업데이트 성능 최적화를 제대로 할 수 있다.

예시

function InputSample() {
  const [inputs, setInputs] = useState({
    name: '',
    nickname: ''
  });

  const { name, nickname } = inputs; // 비구조화 할당을 통해 값 추출

  const onChange = (e) => {
    const { value, name } = e.target; // 우선 e.target 에서 name 과 value 를 추출
    setInputs({
      ...inputs, // 기존의 input 객체를 복사한 뒤
      [name]: value // name 키를 가진 값을 value 로 설정
    });
  };

  const onReset = () => {
    setInputs({
      name: '',
      nickname: '',
    })
  };

  return (
    <>
      <input name="name" placeholder="이름" onChange={onChange} value={name} />
      <input name="nickname" placeholder="닉네임" onChange={onChange} value={nickname}/>
      <button onClick={onReset}>초기화</button>
      <div>: {name} ({nickname})
      </div>
    </>
  );
}

6. useRef

1) 특정 DOM 선택

useRef() 를 사용하여 Ref 객체를 만들고,
이 객체를 우리가 선택하고 싶은 DOM 에
ref 값으로 설정해주면 된다.
그러면 Ref 객체의 .current 값은 우리가 원하는 DOM을 가리키게 된다.

함수형 컴포넌트 : useRef()
클래스형 컴포넌트 : 콜백함수나 React.createRef

2) 컴포넌트 안의 변수 만들기

useRef를 이용해 컴포넌트 안에서 조회 및 수정 할 수 있는 변수를 관리 할 수 있다.

리액트 컴포넌트의 상태는 상태를 바꾸는 함수를 호출하고 나서
렌더링 된 이후에 업데이트 상태를 조회할 수 있지만,

useRef로 관리하는 변수는 설정 후 바로 조회가 가능하다.

파라미터를 넣어주면, .current의 기본값이 되며
수정, 조회시 .current를 조회하면 된다.

7. 배열

Key의 존재유무에 따른 업데이트 방식

1) Key가 없을때

const array = ['a', 'b', 'c', 'd'];
arry.map(item => <div> {item} </div>)

b와 c 사이에 z를 넣을때
c -> z, d -> c, 마지막 -> d
a 제거, a -> b, b-> z, z -> c, c->d, 마지막의 d 제거

2) Key값이 있을 때

const array = ['a', 'b', 'c', 'd'];
arry.map((item, index) => <div key={index}> {item} </div>)

수정되지 않는 기존의 값은 그대로 두고
원하는 곳에 내용을 삽입하거나 삭제

불변성 유지!

1) 추가

spread 연산자나 concat 함수 (O)
배열의 push, splice, sort 등의 함수 (X)

2) 제거

filter 함수

3) 수정

map 함수

// App.js
import React, { useRef, useState } from 'react';
import UserList from './UserList';
import CreateUser from './CreateUser';

function App() {
  const [inputs, setInputs] = useState({
    username: '',
    email: ''
  });
  const { username, email } = inputs;
  const onChange = e => {
    const { name, value } = e.target;
    setInputs({
      ...inputs,
      [name]: value
    });
  };
  const [users, setUsers] = useState([
    {
      id: 1,
      username: 'velopert',
      email: 'public.velopert@gmail.com',
      active: true
    },
    {
      id: 2,
      username: 'tester',
      email: 'tester@example.com',
      active: false
    },
    {
      id: 3,
      username: 'liz',
      email: 'liz@example.com',
      active: false
    }
  ]);

  const nextId = useRef(4);
  // 추가
  const onCreate = () => {
    const user = {
      id: nextId.current,
      username,
      email
    };
    setUsers(users.concat(user));

    setInputs({
      username: '',
      email: ''
    });
    nextId.current += 1;
  };

  // 제거
  const onRemove = id => {
    // user.id 가 파라미터로 일치하지 않는 원소만 추출해서 새로운 배열을 만듬
    // = user.id 가 id 인 것을 제거함
    setUsers(users.filter(user => user.id !== id));
  };
  // 수정
  const onToggle = id => {
    setUsers(
      users.map(user =>
        user.id === id ? { ...user, active: !user.active } : user
      )
    );
  };
  return (
    <>
      <CreateUser
        username={username}
        email={email}
        onChange={onChange}
        onCreate={onCreate}
      />
      <UserList users={users} onRemove={onRemove} onToggle={onToggle} />
    </>
  );
}

export default App;

// UserList.js

import React from 'react';

function User({ user, onRemove, onToggle }) {
  return (
    <div>
      <b
        style={{
          cursor: 'pointer',
          color: user.active ? 'green' : 'black'
        }}
        onClick={() => onToggle(user.id)}
      >
        {user.username}
      </b>
      &nbsp;
      <span>({user.email})</span>
      <button onClick={() => onRemove(user.id)}>삭제</button>
    </div>
  );
}

function UserList({ users, onRemove, onToggle }) {
  return (
    <div>
      {users.map(user => (
        <User
          user={user}
          key={user.id}
          onRemove={onRemove}
          onToggle={onToggle}
        />
      ))}
    </div>
  );
}

export default UserList;
profile
slowly but surely

0개의 댓글