js파일, jsx파일의 차이점은 없다. 단지 명시적으로 jsx로 쓰인 코드면 jsx파일로 만든다. 대부분의 회사에서는 대부분의 컴포넌트는 jsx로 쓴다.
mount
import React, { useEffect, useState } from 'react'
function Loading() {
const [isLoaded, setIsLoaded] = useState(false)
useEffect(() => {
// 컴포넌트가 렌더링될때 실행될 함수
// 데이터 갖고오기 요청 보내고, 데이터가 오면 isLoaded = true
setTimeout(() => {setIsLoaded(true)}, 3000)
}, [])
return (
<div>
{isLoaded ? <>로딩 완료!</> : <>로딩 중</>}
</div>
)
}
update
function Loading() {
const [isLoaded, setIsLoaded] = useState(false)
const [text, setText] = useState([])
useEffect(() => {
// 컴포넌트가 렌더링될때 실행될 함수
// 데이터 갖고오기 요청 보내고, 데이터가 오면 isLoaded = true
setTimeout(() => {setIsLoaded(true)}, 3000)
}, [])
// 로딩이 완료로 변하면 실행
useEffect(() => {
// 업데이트될 때 실행되는 함수 + 처음 컴포넌트가 렌더될때도 실행된다.
if(isLoaded) setText(text.concat([' 추가!']))
}, [isLoaded]) // 너가 여기 안에 쓴 그 값이 업데이트되지 않은 상태로 반영이 될수있으니 text를 지켜보도록 작성을 해라 하지만 우리의 목적과는 별개이기도 하고 text변수도 넣어주면 재귀적으로 '추가!' 문자가 추가된다.
return (
<div>
{isLoaded ? <>로딩 완료!</> : <>로딩 중</>}
{text}
</div>
)
}
import React, { useEffect, useState } from 'react'
function Timer({s}) {
const [seconds, setSeconds] = useState(s)
const [isClicked, setIsClicked] = useState(false)
useEffect(() => {
if(isClicked) {
const countDown = setTimeout(() => {setSeconds(seconds - 1)}, 1000)
return () => clearTimeout(countDown) // 컴포넌트가 꺼질때 셋타임아웃도 꺼진다.
}
}, [seconds, isClicked]) // 지켜볼 변수
return (
<div>
<div>{seconds}</div>
<button onClick={() => setIsClicked(true)}>타이머 시작</button>
<button onClick={() => setIsClicked(false)}>타이머 종료</button>
</div>
)
}
export default Timer
import React, { useState, useEffect } from 'react'
import moment from 'moment'
function Clock() {
const [time, setTime] = useState(moment().format('YYY-MM-DD HH:mm:ss'))
useEffect(() => {
const seoul = setTimeout(() => setTime(moment().format('YYY-MM-DD HH:mm:ss')), 1000)
return clearTimeout(seoul)
}, [time])
return (
<>
<strong>현재 시각</strong>
<p>{time}</p>
</>
)
}
export default Clock
CRA로 프로젝트를 만들면 클래스를 이렇게 작성되도록 플러그인이 설치가 되어있다.
import React, { Component } from 'react';
class Comp extends Component {
// const [num, setNum] = useState(0)과 같다.
state = {
num: 0
}
countUp = () => {
this.setState({
num: this..state.num + 1. // 위에 작성한 state 안의 num 값을 갖고 오게 됨
})
}
render() { // render() 를 붙여줘야만 렌더가 됨
const { name } = this.props; // 클래스는 props에 this를 붙여줘야한다.
return (
<div>
<h1>{this.state.num}</h1>
<button onClick={this.countUp}>카운트 업!</button>
</div>
);
}
}
export default Comp;
인자가 없을때는 이벤트가 자동으로 넘어간다.
const onUserInputChange = (e) => {
const { name, value } = e.target
setUserInput({...userInput, [name]: value}) // id 또는 pw만 할당되는 상황이라서 ...전개 연산을 해줌으로써 id와 pw에 각각 데이터가 들어가고서 다시 합쳐서 들어온다
}
<input placeholder='아이디를 입력해주세요' onChange={onUserInputChange} name="id"/>
<input placeholder='비밀번호를 입력해주세요' onChange={onUserInputChange} type="password" name="pw"/>
const KeyHandler = (e) => {
if(e.key === 'Enter') {
// 엔터 눌렀을때 실행될 것
}
}
<input onKeyDown={KeyHandler} />
로그인시 input값 가져오기
onChange 또는 ref를 활용해서 input값을 가져온다.
하지만 onChange를 더 많이 사용한다.
실시간 예외처리와 상태관리에 더 장점이 있어서이다.
재렌더링 되지 않는 효율적인 변수 만든다. 값이 변해도 재렌더링이 되지 않는 변수를 만들고자 할 때 사용할 수 있다. 변수 만드는 과정에서 메모리를 최소화하고 싶을때 useRef
를 쓰게된다.
어떤 요소를 제거할때 filter 메서드가 가장 옳은 방식이다.
const [times, setTimes] = useState([{id: 1, tz: 'Asia'}, {id: 2, tz: 'America'}])
<button onClick={() => {setTimes(time.filter(timeElement => timeElement.id !== time.id))}}> 제거하기<button>