import React from "react";
import axios from"axios";
class App extends React.Component {
state={
isLoading: true
};
componentDidMount(){
axios.get("https://yts-proxy.now.sh/list_movies.json")
}
render(){
const { isLoading } = this.state;
return<div>{isLoading ? "Loading..." : "We are ready"}</div> // 자바스크립트의 삼항연산자라고 한다 true일시 Loadingd이 false일때 We are ready가 출력되게 만든다.
}
}
export default App;
넣고나서 웹의 Network 창에 보면 무언가 요청하는것이 많은것을 확인할 수 있다.
그리고 아무것도 안나오는것은 우리가 아무것도 안하기 때문이다
우리가 해야할일은 이제 api에서 오는 data를 잡아와야한다 그래야 state안에 사용할 수 있다.
axios.get은 느리다. 그래서 자바스크립트에게 componentDidMount 함수가 끝날 때 까지 약간 시간이 걸릴 수 있다고 말해야하고 우리는 기다려야한다. 그렇게 하기위해 우리는 componentDidMount앞에 async를 넣어줄 것이다.
그리고 우리는 getMovies function을 만든다. 또한 얼마나 기다려야하는지 알려주어야 하기 때문에
axios.get() 옆에 await이라고 적어주자 . 안적어주면 자바스크립트는 기다려주지 않는다. 그리고 이걸 하기위해서 더많은 코드가 필요한 다른일을 해야한다고 한다 그래서 이경우 우리는 async await을 사용해야 한다고 한다.
#4.1 Fetching Movies from API
음 axios를 이용해서 console창에 무엇이 나오는지 확인하고 state안에 넣을 것을 추려낸다.
import React from "react";
import axios from"axios";
class App extends React.Component {
state={
isLoading: true
};
getMovies = async ()=>{
/*
이방법은 효율적이지 않다고한다
const movies = await axios.get("https://yts-proxy.now.sh/list_movies.json")
console.log(movies.data.data.movies); //데이터를 가져오고나서 무엇을 가져왔나 확인하기 위해 작성
*/
// 단축버전
const {data:{data:{movies}}} = await axios.get("https://yts-proxy.now.sh/list_movies.json")
console.log(movies)
}
componentDidMount(){
this.getMovies();
}
render(){
const { isLoading } = this.state;
return<div>{isLoading ? "Loading..." : "We are ready"}</div> // 자바스크립트의 삼항연산자라고 한다 true일시 Loadingd이 false일때 We are ready가 출력되게 만든다.
}
}
export default App;
이런식으로 작성하게되면
state에 넣어야할 내용들을 추려진것을 확인할 수 있다.
state에 movies 배열을 생성하고 스테이트값을 설정해주는데 여기서 전의 자바스크립트라면 this.setState(movies:movies) 이렇게 작성해서 state의 movies는 axios의 movies라고 만들어줘야하는데 최신es6의 자바스크립트는 그냥 통일해서 movies라 작성해도 된다고 한다. 그리고 웹을 보면 바뀌는 반응이 없을텐데 그래서 우리는 isLoading의 값을 바꿔주어야한다. isLoading을 false로 하고 아래에 render로 가보면 we are ready가 써있는것을 확인할 수 있는데 이는 멋지지 않다 그래서 우리는 movies.js라는 새로운 파일을 만들어보자
import React from "react";
import axios from"axios";
class App extends React.Component {
state={
isLoading: true,
movies: []
};
getMovies = async ()=>{
/*
이방법은 효율적이지 않다고한다
const movies = await axios.get("https://yts-proxy.now.sh/list_movies.json")
console.log(movies.data.data.movies); //데이터를 가져오고나서 무엇을 가져왔나 확인하기 위해 작성
*/
// 단축버전
const {data:{data:{movies}}} = await axios.get("https://yts-proxy.now.sh/list_movies.json");
console.log(movies);
this.setState({movies, isLoading: false})
// state에 movies 배열을 생성하고 스테이트값을 설정해주는데
// 여기서 전의 자바스크립트라면 this.setState(movies:movies) 이렇게 작성해서
// satte의 movies는 axios의 movies라고 만들어줘야하는데
// 최신es6의 자바스크립트는 그냥 통일해서 movies라 작성해도 된다고 한다.
// 그리고 웹을 보면 바뀌는 반응이 없을텐데 그래서 우리는 isLoading의 값을 바꿔주어야한다.
// isLoading을 false로 하고 아래에 render로 가보면 we are ready가 써있는것을 확인할 수 있는데
// 이는 멋지지 않다 그래서 우리는 movies.js라는 새로운 파일을 만들어보자
};
componentDidMount(){
this.getMovies();
}
render(){
const { isLoading } = this.state;
return<div>{isLoading ? "Loading..." : "We are ready"}</div> // 자바스크립트의 삼항연산자라고 한다 true일시 Loadingd이 false일때 We are ready가 출력되게 만든다.
}
}
export default App;
movies.js 파일을 만들고 할일은 movies를 render할 것이다.
작성하기 이전에 가져올 데이터를 찾아보자 아까 적어준 API 주소에 들어가보자
들어가면 이렇게 가져올 항목들이 주루룩 뜨는데 여기서 맘에 드는것을 가져와 Movie.js에 작성해준다.
수업 영상을 보고 영상이 진행되는 순서에 맞춰 바로바로 작성하다 보니 장황하고 말 이상하게 쓸 수도 그리고 뇌피셜로 적는 내용이 있을 수 있고 빠짐없이 적고자 하지만 놓친 부분이 있으니 수업내용이 궁금하면 직접 보는 걸 추천드립니다.
결정적으로 웹 HTML만 조금 배운상태에서 진행한거여서 완벽하지 않습니다
아마 이글을 보는 사람이 없을 거 같기는 한데 노파심에
#3. STATE
#3. 0 Class Components and State
1. 기존 존재하는 component들을 지우고 app component를 function component에서 class component로 변경한다.
2. 이후 app component도 지우고 결과적으로 class app component를 만드는데 React.Component를 상속받는다.
ex)
핸드폰 게임을 개발한다면 samsung을 iphone을 프로그래밍하지 않고 cell phone을 프로그래밍한다.
cell phoene 은 여러 가지 특성이 있다. 예를 들면 screen, charger 등등
iphone과 samsung은 이러한 것을 공유한다.
그래서 camera, screnn, charger를 cell phone class에 넣은 다음에서 확장한 samsung class를 가지게 된다.
위에서의 React.Component를 상속받고 만든 class app component는 기본적으로 react class component에서 가져오고 있다. 그리거 거기서 확장하고 있다. 결과적으로 App component는 react component이다.
3. function component와 class component의 차이
- function component는 return을 통해 반환한다. 하지만 class component는 반환을 하지 않는다. function이 아니기에
- 그리고 class react component에는 render method를 가지고 있다.
현재 react component를 상속한 class App component도 동일하게 react component를 가지고 있다.
render 메서드 안에서 리턴 html 문을 작성하면 출력이 되는 것을 확인할 수 있다.
import React from "react";
import PropTypes from"prop-types";
class App extends React.Component {
render() {
return <h1>im a class component</h1>;
}
}
export default App;
결과적으로
Function component는 function이고 뭔가를 return 한다 그리고 screen에 표시가 되고
class component는 class이다 하지만 react component로부터 확장되거 screen에 표시가 된다.
그리고 화면에 표시하기 위해선 render 메서드 안에 넣어야 하고 react는 자동적으로 모든 class component의 render method를 실행하고자 한다.
react는 자동적으로 나의 class component의 render method를 실행한다 자동으로
그 자바 보면 컴파일하려면 main 메서드부터 읽어오는 그러는 느낌인가
4. state는 object이고 component의 data를 넣을 공간이 있고 이 data는 변한다.
그리고 state를 render 안에 넣으려면 class 이기에 this.로 표현해주어야 한다.
import React from "react";
import PropTypes from"prop-types";
class App extends React.Component {
state = {
count: 0
};
render() {
return <h1>im a class component {this.state.count}</h1>;
}
}
export default App;
결과적으로 우리는 state에 바꾸고 싶은 data를 넣는 것
일단 소스코드부터 보고 작성하겠다.
import React from "react";
import PropTypes from"prop-types";
class App extends React.Component {
state = {
count: 0
};
add = () => {
console.log("add");
};
minus = ()=>{
console.log("minus");
};
render() {
return(
<div>
<h1>this number is:{this.state.count}</h1>
<button onClick={this.add}>Add</button>
<button onClick={this.minus}>Minus</button>
</div>
)
}
}
export default App;
일단 보면 add =() =>{} 안에 적혀 이 쓴 게 두 개가 보인다. 이는 javascript 언어라고 한다.
뭘 의미하는지는 정확히 모르겠지만 console.log("add"); 를 나타내게 해주는 역할을 하는 것 같다.
그리고 아래 render 쪽을 보면 두 개의 버튼이 만들어진 것을 확인할 수 있는데 이는 react에서만 작용한다고 한다. 아무튼
이렇게 버튼 두 개에 onClick을 적어 버튼을 눌렀을 때 this.로 위에 만들어진 add와 minus를 실행하게 하는 것 같은데
여기서 주의할게 thsi.add()로 작성하게 된다면 버튼을 누르기도 전에 생성이 된다고 한다. 클릭될 때 동작하게 하려면 ()를 빼주어야 한다고 한다.
아무튼 이렇게 작성 후 버튼을 여러 번 누르고 콘 살창을 확인해보면 숫자가 올라가 있는 것을 확인할 수 있다.
#3. 1 All you need to know about State
State값을 변경하면 웹에 바뀌지 않는 것을 확인할 수 있다. 이는 왜 그러냐면 state값을 변경하면 다시 render를 실행시켜주어야 하는데 실행이 안되어서 업데이트가 되지 않는다. 그래서 우리는 setState를 사용해야 한다. setState를 사용해 값을 변경하면 react는 바로 state를 refresh 하고 바로 render를 불러온다고 한다.
import React from "react";
import PropTypes from"prop-types";
class App extends React.Component {
state = {
count: 0
};
add = () => {
this.state=2;
};
minus = ()=>{
this.setState({count:-1});
};
render() {
return(
<div>
<h1>this number is:{this.state.count}</h1>
<button onClick={this.add}>Add</button>
<button onClick={this.minus}>Minus</button>
</div>
)
}
}
export default App;
위와 같이 add에서는 this.state=로 설정하고 minus는 setState를 이용해서 설정하고 버튼을 눌렀을 때
add버튼 같은 경우 아무 반응이 없고 minus버튼을 누르면 count가 -1로 변경돼서 바로 바뀌는 것을 볼 수 있다.
이는 html 코드로 본다면 react에서 필요한 부분을 빠르게 추가해서 표시해주는 걸 확인할 수 있는데 이때의 속도는 엄청나게 빠르다고 한다.
setState를 사용하지 않으면 새 state와 함께 render function이 호출되지 않을 것이다.
수업 영상을 보고 영상이 진행되는 순서에 맞춰 바로바로 작성하다 보니 장황하고 말 이상하게 쓸 수도 그리고 뇌피셜로 적는 내용이 있을 수 있고 빠짐없이 적고자 하지만 놓친 부분이 있으니 수업내용이 궁금하면 직접 보는 걸 추천드립니다.
아마 이글을 보는 사람이 없을 거 같기는 한데 노파심에 ㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎ
이 부분을 reactJS에서는 component라고 부른다 component의 역할은 보다시피 html을 반환하는 함수이다.
그리고 밑줄 친 부분은 우리가 component를 사용하고자 할 때의 component의 형태이다.
react는 component를 사용해서 html처럼 작성하려는 경우 <App/> 이형식을 가져야 한다.
그리고 javascript와 HTML사이의 이러한 조합을 jsx라고 부른다.
react에서 자바스크립트와 유일하게 배우는 것..?
이렇듯 위의 사진은 component를 사용하는 방법이다.
우리만의 component를 만드는 것은 간단하다
1.src폴더 안에 Potato.js 파일을 만든다.
만들고 component를 만들 때는 항상 import React from "react"; 를 작성해주어야 한다.
안 해주면 react는 여기에 jsx가 있는 component를 사용하는 것을 이해하지 못한다고 한다.
작성 후 아까 hello를 작성했을 때와 동일하게 작성하면 되는데 함수 안에 내용을 작성을 하면
에디터에서 사용되지 않는 함수라고 나오는데 이를 해결하기 위해
export 해주어야 한다고 한다.
이렇게 만든 component를 사용하려면 일단 첫 번째로 생각해볼게 index.js파일에 가서 <App/>이 사용되었듯
Potato를 Import 해서 <App/> 옆에 작성하여 <App/>과 <Potato/>를 react가 가져가게 할 거라고 생각할 수 있는데
react는 하나의 component만을 rendering 해야 하기 때문에 오류가 나오는 것을 확인할 수 있다고 확인하고 해 보는데 잘되는데.. 버전 업데이트를 통해 지원이 가능한 건지는 모르겠는데 나는
이렇게 작성하고 예시를 보여줬는데 동영상에서는 오류가 나왔다. 그런데 1년 전 자료라 그런지 버전 업데이트를 통해 고쳐진 거일지도 모르겠다.
흠 일단 다음 영상을 계속 보면서 이 부분은 따로 알아봐야겠다.
일단 jsx는 javascript 안의 HTML이라고 한다.
음 이 부분을 어떻게 설명해야 할지 모르겠는데 위와 같이 component를 따로 만들어서 사용하면 파일을 왔다 갔다 해야 하는 복잡함이 생겨서 삭제하고 app component안에서 작업을 하는데
위 사진과 같이 App component 안에서 Potato component를 생성해서 App component 안에 넣어 중복해서 사용할 수 있음을 알 수 있다.
예를 들어 i like pizza, i like kimchi와 같이 i like는 동일하게 사용하고 음식만 다른 음식으로 다르게 사용하고자 할 때 component를 여러 개 만들어서 app component에 넣는 것이 아닌 props를 이용하여 Potato component를 인자(argument)를 받게 만들고 {} 감싸고 Potato 부분도 {}로 감싸면 변경해서 계속 사용할 수 있다.
알아보기 쉽게 편의상 Potato -> Food로 바꾸겠다.
+ Component 이름은 대문자로 시작해야 한다.
#2. 2
위와의 방법은 음식을 추가할 때마다 복사 붙여 넣기를 해야 하기 때문에
웹사이트에 동적 데이터를 추가하는 방법
Map을 사용해서 나오게 할 것이며 Map은 Array를 불러와 내가 원하는 arrray로 만들어 가져와주는 역할을 한다.
첫 번째로 일단 좋아하는 음식을 배열로 하나 만든다.
import React from "react";
function Food ( {name}){
return <h1>i like {name}</h1>;
}
const foodlike = [
{
name :"kimchi"
},
{
name : "chicken"
},
{
name : "pizza"
}
]
function App() {
return (
<div>
{foodlike.map( dish=> <Food name={dish.name} />)}
</div>
)
}
export default App;
위를 보면 일단 foodlike를 배열로 만들고
아래 app component에서 map을 만들고 dish라는 이름으로 부르도록 설정한다. 이건 각각의 item인 kimchi chicken pizza를 나타낸다 그러고 위에서의 Food component에 이름을 넘겨주기 위해 dish.name을 적어준다.
그리고 이제 이 음식 사진을 추가적으로 넣어보자.
일단 소스코드는
import React from "react";
function Food ( {name, picture}){
return (
<div>
<h2>i like {name}</h2>
<img src={picture} />
</div>
);
}
const foodlike = [
{
name :"kimchi",
img : "https://www.koreanbapsang.com/wp-content/uploads/2016/10/DSC_1843-e1477360668451.jpg"
},
{
name : "chicken",
img : "https://www.maangchi.com/wp-content/uploads/2018/02/roasted-chicken-1.jpg"
},
{
name : "pizza",
img : "https://www.hapskorea.com/wp-content/uploads/2019/08/black-angus-lobster-ball-pizza.jpg"
}
]
function App() {
return (
<div>
{foodlike.map( dish=> (<Food name={dish.name} picture={dish.img}/>) )}
</div>
)
위와 같이 foodlike에 이미지를 넣어주고
아래 map에 dish.img를 받는 문구를 적고 위에 food에서 이미지를 받는 프로그래밍을 해준다.
이후 renderFood component를 만들어서 foodlike.map에 음식과 이미지 정보를 받아 food component에 넘겨주어 웹에 출력하도록 만들고 app component에 이 쓴 foodlike.map 코드를 간결하게 만들어본다. 그리고 이후에 foodlike.map에
console.log를 적어 웹에서 어떤 식으로 긁어와서 출력되는지 확인한다.
import React from "react";
import {render} from "@testing-library/react";
function Food ( {name, picture}){
return (
<div>
<h2>i like {name}</h2>
<img src={picture} />
</div>
);
}
const foodlike = [
{
name :"kimchi",
img : "https://www.koreanbapsang.com/wp-content/uploads/2016/10/DSC_1843-e1477360668451.jpg"
},
{
name : "chicken",
img : "https://www.maangchi.com/wp-content/uploads/2018/02/roasted-chicken-1.jpg"
},
{
name : "pizza",
img : "https://www.hapskorea.com/wp-content/uploads/2019/08/black-angus-lobster-ball-pizza.jpg"
}
]
function renderFood (dish) {
return <Food name={dish.name} picture={dish.img}/>
}
function App() {
return (
<div>
{console.log(foodlike.map(renderFood))}
{foodlike.map(renderFood)}
</div>
)
}
export default App;
웹에서는 출력이 잘되지만 console창에서 보면 오류가 나와있는 걸 볼 수 있다.
list 내의 child는 unique 한 key prop을 가져야 한다고 나와있다.
그래서 foodlike component의 배열 값들에 id값을 준다. id 값을 주고 오류에서 나온 key값을 정해준다.
이후 웹페이지에 돌아가서 console창을 확인해보면 오류가 안 나와있는 것을 확인할 수 있다.
import React from "react";
import {render} from "@testing-library/react";
function Food ( {name, picture}){
return (
<div>
<h2>i like {name}</h2>
<img src={picture} />
</div>
);
}
const foodlike = [
{
id:1,
name :"kimchi",
img : "https://www.koreanbapsang.com/wp-content/uploads/2016/10/DSC_1843-e1477360668451.jpg"
},
{
id:2,
name : "chicken",
img : "https://www.maangchi.com/wp-content/uploads/2018/02/roasted-chicken-1.jpg"
},
{
id:3,
name : "pizza",
img : "https://www.hapskorea.com/wp-content/uploads/2019/08/black-angus-lobster-ball-pizza.jpg"
}
]
function renderFood (dish) {
return <Food key={dish.id} name={dish.name} picture={dish.img}/>
}
function App() {
return (
<div>
{console.log(foodlike.map(renderFood))}
{foodlike.map(renderFood)}
</div>
)
}
export default App;
결과적으로 foodlike에 id값을 준 것은 food component에서는 사용하지 않는다 기본적으로 react에서 사용하기 위해 설정해준 것이다. react에서는 모든 element들이 다르게 보일 필요가 있다. id값을 주기 이전의 foodlike의 코드를 보면 우리는 각각의 사진과 이름을 가지고 있다는 것을 알지만 react는 알지 못하기에 우리가 이렇게 id값을 정해주고 key를 넣어주는 것
+ 추가적으로 img 태그에서 alt ={name} 이 부분이 없었는데 이번 영상을 보면서 나는 못 적은 부분이 적혀있길래 내가 놓친 부분이라고 생각했는데 추가적으로 이영상 뒤에 설명이 나왔다 img 태그에는 alt prop 이 반드시 있어야 하고 있어야 하는 이유에는 시각장애인들을 위해 있어야 한다고 한다.
#2. 4 Protection with PropTypes ( props에 원하는 props가 들어가 있는지 점검하기)
- father component로부터 전달받은 props가 우리가 예상한 props 인지
1. foodlike에 있는 각각의 음식에 rating(점수 매겨보기 )
2. 이후 터미널에 npm i prop-types 입력하여 기능(?) 설치
- 이를 설치하여 아까 작성했던 코드에서 picture를 보내야 하는데 image를 보낸다면 component가 잘못될 텐데
cmd창에 documents에 접속 후 npx명령어와 만들 app의 이름을 설정해주고 실행한다.
설치가 완료되면 이렇게 나온다.
6. VSC로 돌아가서..
documents에 생성된 movie_app_lsw을 열면 목록에 여러 가지 나오는데 그중
package.json에 들어가서 start, build만 남기고 나머지는 지워준다 안 쓴다고 한다.
터미널 창에 npm start를 입력해 만든 movie_app_lsw을 시작해보자
시작이 정상적으로 되었다면 이화면을 확인할 수 있다.
7. 만든 것을 깃허브에 넣자
vsc 터미널을 이용해서 깃허브에 넣을 건데
터미널에 입력 시 깃허브의 저장소를 만들어주어야 하는데
이런 식으로 만들고
터미널에 이렇게 넣으면 되는데 커밋을 잘 못써서 두 번 썼는데 위에 한 줄만 저렇게 써주면 된다. 그리고 푸시하고 확인하면 저장소에 들어간 모습을 확인할 수 있다.
8. 만들어진 경로의 폴더를 살펴보면
3가지의 폴더 중 src폴더의 index파일의 3,5번 라인의 글을 지운다. 기본적인 설명을 위해 불필요한 부분을 지운다고 한다.
더불어 14,15,16,17 라인도 지운다.
그리고 소스 폴더에 있는 몇 가지 파일을 지운다.
그리고 App.js에서 import logo 부분을 삭제한다. (로고 파일을 지웠기 때문에)
더불어 div를 비워준다
이렇게 했는데 오류가 나와서 처음부터 다시 하는데 vsc는 익숙지 않아 쓰던 intellij를 이용해 다시 했는데 홈페이지에서 오류가 나오는 것이다. 이미지 파일을 찾을 수 없다나 그래서 잘 보니 리턴 바로 오른쪽에다 div태그가 있어야지 된다. 아무튼 저렇게 작성하면
빈화면이 나온다.
작동 은하지만 아무것도 나타내지 않는 빈공 백의 상태의 페이지를 확인할 수 있다.
그 후 appjs에 div태그를 감싸 hello!! 를 작성하면 hello! 가 출력이 되는 것을 확인할 수 있다.
여기서 웹에서 소스코드를 확인해보면 아래쪽에 div태그 안에 hello 있는 것을 확인할 수 있다.
그런데 에디터에서 public 폴더의 index.html 파일에 들어가면 내가 div태그 안에 작성한 hello는 찾아볼수 없는데 이것이 react가 html을 사용하는 방법이다 react는 처음부터 html을 넣지 않고, html에서 html을 추가하거나 제거하는 방법을 알고있다. 그래서 application에서 이것을 로드할때 빈 html을 로드하게 되고 그런다음에 react가 html을 밀어넣게 된다 방금 작성한 div태그안에 hello를
이를 증명(?) 하는 자료로는 index.js의 파일 안에는 getElementByID가 있는데 public의 index.html에도 getElementByID의 값인 root가 존재하는 걸 확인할 수 있다.
이렇게 빈 html에 react가 html을 추가해서 넣는 게 react의 작동방식이라고 한다.
virtual DOM : virtual document object model
가상의 존재 소스코드에서는 존재하지 않지만 react가 만들어낸다
이렇게 작동하면 엄청 속도가 빠르다고 한다 가상이고 존재하지 않아서...
뇌피셜로는 필요할 때마다 코드(?)들을 넣어줘서 처음부터 코드(?) 전체를 넣고 시작하지 않아도 돼서 빠른 건가