React 기초공부 - 3

솔다·2023년 2월 10일
0

자바스크립트 표현

React 에서 사용하는 JSX는 DOM요소를 단순히 렌더링 하는 기능 외에도 자바스크립트 표현식을 쓸 수 있다. 아래의 예시를 보자

import React from 'react';

function App() {
const name = '리액트';
retunr (
	<>
    	<h1>{name}안녕</h1>
    </>
  );
}

export default App;

let/ var/ Const

let 은 동적인 값을 담을 수 있는 변수를 선언할 때 사용하는 키워드입니다. const는 한번 지정하고 나면 변경이 불가능한 상수를 선언할 때 사용하는 키워드입니다.

var키워드는 scope(해당 값을 사용할 수 있는 코드영역)가 함수 단위입니다.

function myFunction(){
	let a = 1;
    if (true) {
    let a = 2;
    console.log(a); // 2
    }
    console.log(a); // 1

내부에서 사용되는 a와 외부에서 선언된 a는 값이 다른 것을 알 수 있다. 편하게 생각하면 기본적으로 변수는 let을, 나머지는 const를 사용하면된다.

JSX 내부에서 자바스크립트 표현식은 if문을 쓸 수 없다. 하지만, 조건에 따라 렌더링 내용을 바꾸고 싶다면 삼항연산자를 쓰면 가능하다. 그리고 &&연산자와 ||연산자도 이용할 수 있다.

Undefined

값이 undefined 인 경우에 이를 리턴해서 렌더링하게 하면 에러가 발생한다. 하지만, Undefined 값을 JSX내부에return <div>{name}</div> 이런식으로 넣게되면 에러는 발생하지 않는다.

Css로 적용되는 Style과 class

React에서 DOM요소에 스타일을 적용할때는 문자열 형태가 아니라 객체형태로 카멜케이스(camelCase)로 작성해야 한다. 또한 class도 <div className = "react"><{name}</div> 이런식으로 작성해야 인식한다.

그리고 일부 태그들은 JSX에서는 전부 닫아줘야 하는데 선언과 동시에 닫을 수 있는 방식으로 self-Closing태그로 작성할 수도있다. <input /> 같이 작성할 수 있다.

Props

Properties를 줄인 말로, 컴포넌트 속성을 설정할 때 사용하는 요소이다. porps 값은 해당 컴포넌트를 불러와 사용하는 부모 컴포넌트에서 설정할 수 있다.

import React from 'react';

const MyComponent = props => {
	return <div>안녕, 내이름은 {props.name}이야.</div>;
    };

export default Mycomponent

위의 자식 컴포넌트에서 {}로 감싸서 props로 받은 데이터를 사용한다.

이제 부모 컴포넌트를 보자

import React from 'react';

const Parent = () => {
	return <MyComponent name = "React" />;
    };

export default Parent

name으로 "React"를 전달해주는 것을 볼 수 있다.

...
MyComponent.defaultProps = {
	name: '기본이름'
    };
...

위와 같이 기본Props값을 추가해주면 props 값을 전달해주지 않아도 설정된 값으로 실행이 된다.

만일 여러개의 Props값이 온다면 어떻게 작성하면 편리할까?

const MyComponent = ({ name, children }) => {
	return (
    	<div>
        	안녕하세요, 제 이름은 {name}입니다. <br/>
            children 값은 {children}입니다.
        </div>
    );
};

export와 default값 세팅 코드는 생략되어 있지만 이런 문법으로 작성할 수 있다.

State

React에서 State란 컴포넌트 내부에서 바뀔 수 있는 값을 의미한다. props는 컴포넌트가 사용되는 과정에서 부모 컴포넌트가 설정하는 값이며, 컴포넌트 자신은 해당 props를 읽기 전용으로만 사용할 수 있다. props를 바꾸려면 부모 컴포넌트에서 바꾸어주어야 한다.

class형 컴포넌트의 state 를 아래의 예시를 보자.

import React, { Component } from 'react';

class Counter extends Component {
	counstructor(props) {
      super(props);
      //state의 초깃값 설정하기
     this.state = {
     number: 0
     };
   }
   render() {
     const { number } = this.state;
     return {
     <div>
       <h1>{number}</h1>
       <button
       // on click 을 통해 버튼이 클릭되었을 때 호출할 함수를 지정합니다.
        onClick={() => {
        this.setState({ number: number + 1 });
      }}
    > + 버튼
    </button>
  </div>
  );
}
}
export default Counter;

constructor 메서드는 컴포넌트의 생성자 메서드이다. 클래스형 컴포넌트에서 constructor 함수를 작성할 때는 반드시 super(props)를 호출해 주어야 한다. 이 함수가 호출되 현재 클래스형 컴포넌트가 상속하고 있는 리액트의 Component 클래스가 지닌 생성자 함수를 호출해 준다.

클래스형 컴포넌트에서 state를 생성해 준 위의 코드에서 render()함수 내부에서 이 컴포넌트를 랜더링 해주는데 이 부분에서 자신의 state값을 호출하기 위해서는 const { number } = this.state; 로 변수선언을 해주는 것을 볼 수 있다.

이후 setState()함수로 값을 변경해주는 것을 볼 수 있다.

함수형 컴포넌트에서 useState 사용하기

Hook에 대해서 앞에 글에서도 포스팅했지만, 조금 더 자세히 알아보자. Hooks를 사용하기 전에 배열 비구조화 할당을 알아야 하는데 객체 비구조화 할당과 비슷하다. 예시를 들면 아래와 같다.

const array = [1,2];
const one = array[0];
const two = array[1];

//완전히 같은 역할을 하는 아래의 코드
const array = [1,2];
const [one, two] = [1,2];

useState 사용하기

아래의 예시는 say.js라는 파일을 하나 만든것이다.

inport React, { useState} from 'react';

const say = () => {
	const [message, setMessage ] = useState('');
	const onClickEnter = () => setMessage('hi');
    const onClickLeave = () => setMessage('bye');
    
    return (
    	<div>
          <button onClick = {onClickEnter}>입장</button>
          <button onClick = {onClickLeave}>톼장</button>
          <h1>{message}</h1>
        </div>
        );
      };
      
 export default Say;

useState()함수의 인자에는 상태의 초깃값을 넣어줍니다. 클래스형 컴포넌트에서의 state 초깃값은 객체 형태를 넣어주어야 하지만, useState에서는 반드시 객체가 아니어도 상관이 없고 초깃값의 형태는 자유입니다.

useState()함수를 호출하면 배열이 반환된다 [state의 현재상태, 상태를 바꾸어주는 함수] . 이렇게 반환된 상태를 바꾸어주는 함수를 세터(Setter)함수라고 한다.즉, 원하는 값으로 state를 바꾸어 주기 위해서는 이 반환된 함수를 호출해서 인자로 넣어주면 되는것!!!

useState()함수의 멋진 점은 여러번 호출할 수 있다는 것이다. 위의 예시를 조금 더 발전시켜보자.

inport React, { useState} from 'react';

const say = () => {
	const [message, setMessage ] = useState('');
	const onClickEnter = () => setMessage('hi');
    const onClickLeave = () => setMessage('bye');
    
    const [color, setColor] = useState('black');
    
    return (
    	<div>
          <button onClick = {onClickEnter}>입장</button>
          <button onClick = {onClickLeave}>톼장</button>
          <h1 style = {{ color }}>{message}</h1>
          <button style={{ color : 'red' }} onClick={() => setColor('red')}
        </div>
        );
      };
      
 export default Say;

이번 코드에서는 화면에서 표시되는 현재 messagecolor를 변경해주는 기능까지 같이 들어간 것이다. 즉 useState()함수를 쓸때마다 새로운 state를 만들어주고 변경까지 가능한 함수를 얻는 것이다.

물론 주의사항도 있다. state의 값을 바꾸어줄때는 setState()함수나 useState()를 통해 리턴된 세터함수를 사용해야 한다.

그렇다면, 배열이나 객체를 업데이트해야 할 때는 어떻게 해야 할까?

배열이나 객체는 사본을 만들어낸 뒤에 그 사본에 원하는 일부 값들을 업데이트 한 후에, 그 사본의 상태를 setState()혹은 useState()함수를 통해 리턴된 세터함수의 인자로 넣어서 함수를 호출한다.

예시를 반드시 써보고 넘어가야 할 것 같아서 예시를 작성해보자.

//객체 다루기
const object = { a:1, b:2, c:3 };
const nextObject = { ...object, b:2 };// 사본을 만들어서 b값만 덮어쓰기

//배열 다루기
const array = [
	{ id: 1, value: true },
    { id: 2, value: true },
    { id: 3, value: false }
];
let nextArray = array.concat({ id: 4 }); // 새 항목 추가
nextArray.filter(item => item.id !==2 ); //id가 2인 항목 제거
nextArray.map(item => (item.id === 1 ? {...item, value: false } : item)); //id 가 1인 항목의 value를 false로 설정

객체에 대한 사본을 만들 때는 spread 연산자라고 불리는 ...를 사용해서 처리하고, 배열에 대한 사본을 만들 때는 배열의 내장 함수들을 활용해서 처리하는 거다.

React의 이벤트 시스템

리액트의 이벤트 시스템은 HTML과 비슷하다. 주의사항 몇가지만 기억하자

  • camelCase로 Event를 작성해야 한다.(예:onclick => onClick)
  • 이벤트에 실행할 자바스크립트 코드를 전달하는게 아니라 함수 형태의 값을 전달한다.
  • DOM 요소에만 이벤트를 설정할 수 있다. => 구체적으로 말하면 div, button, input, form, span등의 요소들에는 이벤트를 설정할 수 있지만, 컴포넌트 자체에는 사용할 수 있다.

App.js에서 EventPractice

이벤트가 발생하는 input이 여러개일때 작업을 하는건 어떻게 할까? 각각의 input에 대해서 작업해주는 방법도 있겠지만, 더 좋은 방법이 있다.

...
state = {
	username : '',
    message : '',
    }

handleChange = (e) => {
	this.setState({
    	[e.target.name]: e.target.value
      });
    }    

render() {
	return (
    <div>
    	<input
        	type = "text"
            name = "username"
            value = {this.state.username}
            onChange={this.handleChange}
        />
         );
    }

input이 만일 두개라면 어떻게 해야 할까. 우리에게는 편리한 방법이 있다. (e)는 event 객체를 의미한다. 이 e를 잘 사용하면 매우 편리하다. 객체 안에서 statekey[]로 감싸면 그 안에 넣은 레퍼런스가 실제 key값으로 사용되기 때문에 e를 사용해서 handleChange()함수가 여러 input에 적용되도록 할 수 있다.

오늘은 여기까지만 하고 추후에 더 착성해보자.

0개의 댓글