*이름 수정되면 안되는 파일
1. public/index.html ➡️ 페이지 템플릿
2. src/index.js ➡️ js 시작점
*src 폴더 : 대부분의 리액트 소스 코드들 이곳에 작성하면 된다. 번들러는 여기서만 작동한다.
*Package.json 파일
-해당 프로젝트에 대한 정보들이 들어있다.
-프로젝트 이름, 버전, 필요한 라이브러리, 라이브러리 버전들이 명시되어 있다.
앱을 시작할 때 사용할 스크립트, 앱을 빌드, 테스트할 때 사용할 스크립트 등이 명시되어 있다.
웹팩은 오픈 소스 자바스크립트 모듈 번들러로써 여러 개로 나누어져 있는 파일들을 하나의 자바스크립트 코드로 압축하고 최적화하는 라이브러리이다.
장점
npm run start -> 이 명령어로 리액트 앱을 시작할 수 있다.
package.json
-> npm run start
, npm run build
, npm run test
,,
*소스 코드 수정으로 텍스트 변경하기
-> App.js 파일에서 텍스트 수정
현재 App.js 파일의 소스 코드를 변경하면 변경한 부분이 화면에 적용된다.
이게 어떠한 순서로 실행되는지 알아본다
public/index.html
html 템플릿 파일이고 div 엘리먼트의 id가 root이다.
src/index.js
자바스크립트의 시작점이다. 여기에서 위에 root id를 가진 div 엘리먼트를 잡아준다.
그렇기에 그 엘리먼트 안에서 화면을 꾸밀 수 있게 되는 것이다.
📍여기서 생기는 의문점
index.html 템플릿이 하나면 한 개의 페이지를 만들 때는 괜찮은데 두 개 이상의 페이지를 만들면❓❓
이와 같은 방식은 전통적인 웹 사이트를 만들 때 사용하는 Multi Page Application이다.
하지만 요즘에는 이러한 방식을 사용하지 않는다.
✅웹사이트 전체 페이지를 하나의 페이지에 담아 동적으로 화면을 바꿔가며 표현
이것을 SPA(Single Page Applicaton)이라고 한다.
*SPA에서 화면 변경은 어떻게❓
➡️ 자바스크립트 영역에서 HTML 5의 History API를 사용해서 페이지 전환(브라우징)
-현재 페이지 내에서 화면 이동이 일어난 것처럼 작동하게 해준다.
App.js의 function App()
JSX(Javascript syntax extension)
자바스크립트의 확장 문법이다. 리액트에서는 JSX를 이용해서 화면에서 UI가 보이는 모습을 나타내 준다.
JSX를 이용하면 UI를 나타낼 때 자바스크립트(logic)와 HTML구조(markup)를 같이 사용할 수 있기 때문에 기본 UI에 데이터가 변하는 것들이나 이벤트들이 처리되는 부분을 더욱 쉽게 구현할 수 있다.
또한, createElement를 쉽게 사용하기 위해 사용한다.
이는 매우 편리하기 때문에 거의 모든 사람이 사용한다.
*원래 리액트에서 화면을 그리는 방식
React.createElement API를 사용해서 엘리먼트를 생성한 후(객체가 되낟) 이 엘리먼트를 In-Memory에 저장한다. 그리고 ReactDom.render 함수를 사용해서 실제 웹 브라우저에 그려준다.
모든 UI를 만들때 마다 createElement를 사용해서 컴포넌트를 만들 수는 없다.
그렇기 때문에 JSX를 사용한 후 그걸 바벨(babel)이 다시 createElement로 바꿔서 사용한다.
- 컴포넌트에 여러 엘리먼트 요소가 있다면 반드시 부모 요소 하나로 감싸기
- JSX Key 속성 → 요소의 리스트 나열할 때 Key 넣어주기 → 가상 돔/바뀐 부분 찾을 때 사용
- key는 유니크한 값(index (x))
*중괄호 두 번 사용하는 것
{{display: 'flex'}}
-> 이는 React에서 Javascript 표현식을 JSX 속성에 전달하는 방식이다.
외부 중괄호는 JSX에서 Javascript 표현식을 포함시키고,
내부 중괄호는 Javascript 객체를 만든다.
예를 들어,<form style={{display: 'flex'}}>...</form>
에서
- 외부 중괄호는 JSX에서 Javascript 표현식을 사용하겠다는 것을 나타내고,
- 내부 중괄호 {display: 'flex'}는 Javascript 객체를 만든다. 이 객체는 style 속성에 전달되고 해당 객체의 'display' 속성이 'flex'로 설정된다.
이중 중괄호를 사용하는 것은 React에서 스타일을 동적으로 설정하거나 Javascript값을 JSX에 삽입하는 일반적인 방법으로 이렇게 함으로써 Javascript 코드를 JSX에 통합할 수 있으며, 동적으로 스타일과 데이터를 처리할 수 있다.
1. 하나의 목록 JSX(HTML) 추가하기
2. 하나의 목록 스타일링하기(CSS)
(1) 버튼 스타일링
(2) 리스트 스타일링
체크 박스에 체크 표시를 하면 줄이 가게 만들기 위한 스타일링
=> 동적으로 만들어야 하기 때문에 함수로 만든다
할 일 목록을 하드코딩 X ➡️ map() 메소드 사용
*map 메소드
const array1 = [1, 4, 9, 16];
const map1 = array1.map(x => x*2);
console.log(map1);
// expected ouptput : Array [2, 8, 18, 32]
map 메소드를 사용해서 데이터를 나열할 때 key 속성을 넣어주었다.
리스트에 key 속성을 넣지 않는다면❓
error 발생
리액트에서 요소의 리스트를 나열할 때에는 Key를 넣어줘야 한다.
키는 React가 변경, 추가 또는 제거된 항목을 식별하는 데 도움이 된다.
(가상돔에서 바뀐 부분을 찾을 때 이용)
요소에 안정적인 ID를 부여하려면 배열 내부의 요소에 키를 제공해야 한다.
Key에는 Unique한 값을 넣어줘야 된다.
index 비추천 -> index도 0부터 시작해서 유니크한 값을 가지지만 리스트가 추가되거나 제거되면 key값도 바뀌게 된다.
*filter 메소드
const words = {'spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'};
const result = words.filter(word => word.length > 6);
console.log(result);
// expected out.put: Array ['exuberant', 'destruction', 'present']
1. 클릭 이벤트 발생 시 함수 호출하기
✅ 로그에서 보면 newTodoDate 클릭한 목록이 지워지긴 했는데 화면에서는 아무런 변화x
state, value
리액트에서 데이터가 변할 때 화면을 다시 렌더링 해주기 위해서 사용해야 한다.
React State란, 컴포넌트의 렌더링 결과물에 영향을 주는 데이터를 갖고 있는 객체이다.
State가 변경되면 컴포넌트는 Re-rendering 된다. 또한, State는 컴포넌트 안에서 관리된다.
☑️ state를 바꾸려면
*UI 부분
1. 할 일 목록을 입력하는 부분
*기능 부분
1. 글 입력시 state 변경
화면에 입력이 안됨 -> 렌더링이 안되고 있기 때문 -> state 사용!
입력 버튼 클릭 시 목록에 추가하기
입력란에 있던 글씨 지워주기
특정 객체 또는 배열의 값을 다른 객체, 배열로 복제하거나 옮길 때 사용 (…)
배열 조합, 객체 조합, 기존 배열을 보존
*UI 부분
1. 글 중앙에 선 긋기
*조건부 삼항 연산자
if (a) {
a = "a";
}
else {
a = "b";
}
a ? a = "a" : a = "b";
*코드
import React, {Component} from "react"; // 라이브러리에서 컴포넌트 가져오기
import "./App.css";
// 클래스형 컴포넌트
export default class App extends Component { // 컴포넌트를 사용할 수 있게 상속받음
state = {
todoData : [
/*{
id: "1",
title: "공부하기",
completed: false
},
{
id: "2",
title: "청소하기",
completed: false
}*/
],
value: ""
// 입력한 값 들어있음
};
btnStyle = {
color: "#fff",
border: "none",
padding: "5px 9px",
borderRadius: "50%",
cursor: "pointer", // 마우스 커서 모양
float: "right" // 요소의 플로팅 설정 -> 값을 오른쪽으로 플로팅
}
// 동적 요소 함수로 설정
getStyle = (completed) => {
return {
padding: "10px",
borderBottom: "1px #ccc dotted",
textDecoration: completed ? "line-through" : "none"
}
}
handClick = (id) => {
let newTodoData = this.state.todoData.filter(data => data.id !== id);
console.log('newTodoData', newTodoData);
this.setState({todoData: newTodoData});
}
handleChange = (e) => {
console.log('e', e.target.value);
this.setState({value: e.target.value});
}
handleSubmit = (e) => {
// form 안에 input 전송할 때 페이지 리로드 막아줌
e.preventDefault();
// 새로운 할 일 데이터
let newTodo = {
id: Date.now(),
title: this.state.value,
completed: false
}
// 원래 있던 할 일에 새로운 할 일 더해주기
// 입력하면 value 빈값으로
this.setState({todoData:[...this.state.todoData, newTodo], value: "" });
};
handleComleteChange = (id) => {
let newTodoData = this.state.todoData.map(data => {
if (data.id === id) {
data.completed = !data.completed;
}
return data;
});
this.setState({ todoData: newTodoData});
};
render() { // 컴포넌트 내 메소드, render() 내 UI 작성 / 함수형 컴포넌트에서는 RENDER 메소드 필요 없이 바로 UI 작성 가능
// 일반 html과 달리 class 대신 className 사용
return (
<div className="container">
<div className="todoBlock">
<div className="title">
<h1>할 일 목록</h1>
</div>
{this.state.todoData.map(data => (
<div style={this.getStyle(data.completed)} key={data.id}>
<input type="checkbox" defaultChecked={false} onChange={() => this.handleComleteChange(data.id)} />
{data.title}
<button style={this.btnStyle} onClick={() => this.handClick(data.id)}>x</button>
</div>
))}
<form style={{display: 'flex'}} onSubmit={this.handleSubmit}>
<input
type="text"
name="value"
style={{flex: '10', padding: '5px'}}
placeholder="해야 할 일을 입력하세요."
value={this.state.value}
onChange={this.handleChange}
/>
<input
type="submit"
value="입력"
className="btn"
style={{flex: '1'}}
/>
</form>
</div>
</div>
)
}
}