본문 바로가기

React

React 기초

초기 렌더링

  • 컴포넌트 정의

 

import React from 'react';
  • node_modules 디렉터리의 react모듈을 가져와서 사용

 

jsx 특징

  • 보기 쉬움
  • 높은 활용도

jsx 규칙

  • 부모에 의해 감싸인 요소

  • 자바스크립트 표현
  • if문 대신 조건부 연산자
    • if문 대신 삼항 연산자 사용
  • AND연산자(&&)를 사용한 조건부 렌더링
import React from 'react';

function App() {
	const name = '리리액액트트';
    return <div> {name === '리액트' && <h1>리액트입니다.</h1>}</div>;
}

export default App;
  • undefined를 렌더링하지 않기
    • 함수에서 undefined만 반환하는 렌더링 상황을 만들면 안 됨.
    • undefied일 때, 보여주고 싶은 문구가 있는 경우
import React from 'react';
import './App.css';

function App() {
	const name = undefined;
    return <div>{name || '리액트'}</div>;
}

export default App;
  • 인라인 스타일링
    • 리액트에서 DOM요소에 스타일 적용할 때, 카멜 표기법 사용
      • ex) barckground-color => backgroundColor
import React from 'react';

function App() {

  const name = '리액트';
  const style = {
      backgroundColor : 'black',
      color : 'aqua',
      fontSize : '48px',
      fontWeight : 'bold',
      padding : 16
  };
  return <div style = {style}>{name}</div>

}

export default App;
  • class대신 className
    • CSS클래스를 사용할 때, class가 아닌 className으로 설정

  • 꼭 닫아야 하는 태그
    • 태그는 무조건 닫아주기! 
      • HTML에서는 <input>, <br>태그는 굳이 안닫아줘도 됨
      • JSX에서는 태그 무조건 닫아주기!
        • ex) <input />
  • 주석
    • {/* */}로 작성

 

 

const

  • 한번 지정하고 나면 변경이 불가능한 상수
  • scope : 블록 단위

let

  • 동적인 값을 담을 수 있는 변수
  • scope : 블록 단위
function myFunction() {
	let a = 1;
    if(true) {
    	let a = 2;
        console.log(a);		//2
    }
    console.log(a);			//1
 }
 
 myFunction();

var

  • ES6문법에서 사용 X
  • scope(해당 값을 사용할 수 있는 코드 영역) : 함수 단위
function myFunction() {
	var a = 'hello';
    if(true) {
    	var a = 'bye';
        console.log(a);		//bye
    }
    console.log(a);			//bye
 }
 
 myFunction();

 

 


state, props

state

  • 자신이 들고있는 값 (쓰기 전용이라고 봐도 무방)
  • 컴포넌트 내부에서 변경할 수 있는 값
    • MyComponent.js에서 직접 state값 변경 가능
  • 클래스형 컴포넌트에서 constructor 작성 시
constructor(props) {
	super(props);		//반드시 작성
    this.state = {		//state의 초기값 설정
    	number : 0
    };
}
  • state를 constructor에서 꺼내서 초기값 설정
class Counter extends Component {
  state = {
      number : 0,
      number2 : 0
  };
  
  render() {
  	const {number, numver2} = this.state;	//state를 조회할 때, this.state로 조회.
  }
  
 }
  • state 주의사항
    • state값 변경 시, setState or useState를 사용
      • ex) 배열 or 객체를 업데이트하는 상황
        • 배열 or 객체 사본 생성 => 사본 값 업데이트 => 사본 상태를 setState or 세터함수를 통해 업데이트
//객체 다루기
const object = {a : 1, b : 2, c : 3};
const nextObject = {...object, b : 2};      //사본을 만들어서 b값만 2로 수정

//배열 다루기
const array = [
    {id : 1, value : true},
    {id : 2, value : true},
    {id : 3, value : false}
];

let nextArray = array.concat({id : 4});         //array에 새 항목 추가 
nextArray.filter(item => item.id !== 2);     //id가 2인 항목 제거

//id가 1인 항목의 value를 false로 설정.
nextArray.map(item => (item.id === 1? {...item, value : false} : item));

props

  • 부모 컴포넌트가 자식 컴포넌트한테 전달하는 데이터 (자식 입장에서 읽기 전용)
  • 부모 컴포넌트가 변경할 수 있는 값
    • ex) App.js에서 MyComponent의 props를 변경 가능

 

  • 예제
import React, { Component } from 'react';     //react라이브러리에서 Components 클래스 로딩.

import TOC from './components/TOC'
import Content1 from './components/Content'
import Subject from './components/Subject'

import './App.css';       //App.js가 로드될 때, App.css도 같이 로드해서 스타일 입힘.


class App extends Component {
  //생성자 : state 초기화.  (render()이전에 실행 됨)
  constructor(props) {
    super(props);
    //state 초기화.
    this.state = {
      mode : 'read',
      subject: { title: 'WEB', sub: 'World Wid Web!' },
      welcome : {title : 'Welcome', desc : 'Hello, React!'},
      test: { test1: 'Test1', test2: 'Test2' },
      contents: [
          {id : 1, title : 'A', desc : 'A is a'},
          {id : 2, title : 'B', desc : 'B is b'},
          {id : 3, title : 'C', desc : 'C is c'},
      ],
    }
  }
  render() {
    //test
    console.log('App render');

    var _title, _desc = null;
    if(this.state.mode === 'welcome') {
        _title = this.state.welcome.title;
        _desc = this.state.welcome.desc;
    }else if(this.state.mode === 'read') {
        _title = this.state.contents[0].title;
        _desc = this.state.contents[0].desc;
    }

    return (
      <div className="App">
        <h1 style = {{color : 'Tomato'}}>Subject</h1>
        <Subject
            title = {this.state.subject.title}
            sub = {this.state.subject.sub}
            onChangePage = { function() {
              this.setState({mode : 'welcome'});
            }.bind(this)}
        >
        </Subject>
        <hr></hr>

        <h1 style = {{color : 'Tomato'}}>Subject</h1>
        <Subject
          title={this.state.test.test1}
          sub={this.state.test.test2}
          onChangePage = {function() {
             this.setState({
               mode : 'welcome'
             });
          }.bind(this)}
        >
        </Subject>
        <hr></hr>

        <h1 style = {{color : 'Tomato'}}>TOC</h1>
        {/* <TOC data = {this.state.contents}></TOC> */}
        <TOC
           onChangePage = {function() {
             alert('Wow!');
              this.setState({ mode : 'welcome'});
           }.bind(this)}
            inputContents={this.state.contents}
        ></TOC>
        <hr></hr>

        <h1 style = {{color : 'Tomato'}}>Content1</h1>
        <Content1 title={_title} desc={_desc}></Content1>


      </div>
    );

  }
}

export default App;

 

 

배열 비구조화 할당

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

[ ]로 감싸는 코드

  • [ ] 로 감싸져있는 레퍼런스가 가리키는 실제 값이 key값으로 업데이트
const name = 'variantKey';
const object = {
	[name] : 'value'
};
  • 결과값
    • { 'variantKey' : 'value' }

배열 렌더링

  • 예제
import React from 'react';

function User({user12}) {
    return(
        <div>
            <b>{user12.username}</b><span>({user12.email})</span>
        </div>
    );
}

function UserList() {
    const users = [
        {
            id : 1,
            username : 'jaewoo',
            email : 'aaa'
        },
        {
            id : 2,
            username : 'minji',
            email : 'bbb'
        },
        {
            id : 3,
            username : 'dada',
            email : 'ccc'
        }
    ];

    return(
        <div>
            {/* UserList안의 users의 맵핑 */}
            {/* user파라미터 (UserList안의 users)가 <User user12 = {user} />를 통해 이름과 이메일 출력 */}
            {users.map(user12 => (
                <User user12 = {user12} />
            ))}
        </div>
    );

}

export default UserList;

함수형 컴포넌트로 구현

//함수형 컴포넌트로 구현

import React, {useState} from 'react';

const EventPractice = () => {

    const [form, setForm] = useState({
        username : '',
        message : ''
    });

    const {username, message} = form;

    const onChange = e => {
        const nextForm = {
            ...form,        //기존의 form내용을 이 자리에 복사한 뒤
            [e.target.name] : e.target.value    //타겟의 value값을 타겟의 name값에 저장
        };
        setForm(nextForm);
    };
    const onClick = () => {
        alert(username + " : " + message);
        setForm({
            username : '',
            message : ''
        });
    };
    const onKeyPress = e => {
        if(e.key === 'Enter') {
            onClick();
        }
    };

    return(
        <div>
            <input
                type = 'text'
                name = 'username'
                placeholder = '사용자명'
                value = {username}
                onChange = {onChange}
            />
            <input
                type = 'text'
                name = 'message'
                placeholder = '메세지 입력'
                value = {message}
                onChange = {onChange}
                onKeyPress = {onKeyPress}
            />
            <button onClick = {onClick}>확인</button>
        </div>
    );

};

export default EventPractice;

 

ref

  • 정의
    • HTML태그의 id와 유사
  • 용도
    • DOM을 꼭 직접적으로 건드려야 할 때
      • state만으로 해결할 수 없는 기능
        • 특정 input에 포커스 주기, 스크롤 박스 조작, Canvas 요소에 그림 그리기 등
  • ref 사용하는 방법
    • 콜백 함수를 통한 ref 설정
      • ex) <input ref = { (ref) => {this.input = ref} } />
        • this.input은 input요소의 DOM을 가리킴
        • ref
          • input 요소에 ref 콜백 함수를 props로 전달
        • (ref)
          • 콜백함수의 파라미터
    • createRef 함수를 통한 ref 설정
  • 예제
    • 비밀번호 검증
import React, {Component} from 'react';
import './ValidationSample.css';

class PasswordValidation extends Component{

    state = {
        password : '',
        clicked : false,
        validated : false
    }

    handleChange = (e) => {
       this.setState({
           password : e.target.value
       });
    }
    handleButtonClick = (e) => {
        this.setState({
            clicked : true,
            validated : this.state.password === '0000'
        });
        this.input.focus();
    }
    handleKeyPress = (e) => {
        if(e.key === 'Enter') {
            this.handleButtonClick();
        }
    }

    render() {
        return(
            <div>
                <input
                    type = 'password'
                    value = {this.state.password}
                    onChange = {this.handleChange}
                    className = {this.state.clicked ? (this.state.validated ? 'success' : 'failure') : ''}
                    ref = {ref => this.input = ref}
                    onKeyPress = {this.handleKeyPress}
                />
                <button onClick = {this.handleButtonClick}>검증!</button>
            </div>
        );
    }

}

export default PasswordValidation;

 

useRef로 컴포넌트 안의 변수 만들기

  • 용도
    • DOM을 선택하는 용도
    • 컴포넌트 안에서 조회, 수정할 수 있는 변수 관리
      • useRef로 관리하는 변수 : 값이 변경되어도 컴포넌트 리랜더링X (불필요한 리랜더링 줄임)         

useCallback

  • 정의
    • 컴포넌트 리랜더링될 때마다 새로 만들어진 함수를 사용하지 않도록 최적화
  • 문법
    • useCallback(생성하고 싶은 함수, 배열);
      • 해당 배열이 변경되었을 때만, 함수 생성
  • 예제
import React, {useState, useMemo, useCallback} from 'react';

const getAverage = numbers => {
    console.log('평균값 계산 중...');
    if(numbers.length === 0) return 0;
    const sum = numbers.reduce((a, b) => a + b);
    return sum / numbers.length;
};

const Average = () => {
    const [list, setList] = useState([]);
    const [number, setNumber] = useState('');

    const onChange = useCallback(e => {
        setNumber(e.target.value);
    }, []);     //컴포넌트가 처음 랜더링될 때만 함수 생성.

    const onInsert = useCallback(() => {
        const nextList = list.concat(parseInt(number));
        setList(nextList);
        setNumber('');
    }, [number, list]);     //number 혹은 list가 바뀌었을 때만 함수 생성.

    const avg = useMemo( () => getAverage(list), [list] );

    return (
        <div>
            <input value = {number} onChange = {onChange}/>
            <button onClick = {onInsert}>등록</button>
            <ul>
                {list.map((value, index) => (
                    <il key = {index}>{value}</il>
                ))}
            </ul>
            <div>
                <b>평균값 : </b>{avg}
            </div>
        </div>
    );
};

export default Average;

 

useRef

  • 함수형 컴포넌트에서 ref를 쉽게 사용할 수 있도록
  • 예제
    • 등록 버튼 클릭 => 포커스가 인풋 쪽으로

 

'React' 카테고리의 다른 글

map() 함수  (0) 2021.01.21
useReducer  (0) 2021.01.20
EventHandling  (0) 2021.01.19
Hooks  (0) 2021.01.18
파일 쓰임새  (0) 2021.01.14