————————————————————————————————————————————————————————————————————————————————————————————————
1. 세팅하기
————————————————————————————————————————————————————————————————————————————————————————————————
<생초기 세팅>
-NvM 설치확인
nvm --version
-NvM으로 노드 설치
nvm install [설치할 버전]
-설치완료 후 확인
node -v # 노드 버전 확인 명렁어
-사용할 버전으로 맞추기 (보통 LTS버전 씀)
nvm use [사용할 노드 버전]
-npm으로 yarn 설치 (npm은 노드 설치시 자동으로 설치됨.)(yarn add로 원하는 패키지 설치)
npm install -g yarn
-CRA(create-react-app)으로 시작하는 리액트 설치
yarn add global create-react-app
<프로젝트 시작할 때>
-리액트 프로젝트 생성
yarn create react-app [프로젝트 폴더이름]
-Styled-components 설치
yarn add styled-components
import styled from "styled-components"; (추가 후 사용)
-React-router-dom 설치
yarn add react-router-dom@5.2.1 (강의랑 버전 맞추기 위해 @5.2.1버전으로 설치함, @떼면 최신버전)
-프로젝트 실행(폴더 안에서) (실행종료 control+c)
yarn start
**두번씩 콘솔찍힐때
index.js에서 React.StrictMode 삭제
———————————————————————————————————————————————————————
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
//App.js 받아오고
import { BrowserRouter } from "react-router-dom";
// BrowserRouter 사용 위해 임포트!
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
{/ BrowserRouter로 App.js 감싸주기 /}
);
———————————————————————————————————————————————————————
<2. App.js에서 만들 페이지들 하기 + 모든페이지 공통 props만들어주기>
import React from "react";
import { Route } from "react-router-dom";
// Route 사용 위해 임포트!
import Main from "./Main";
import Detail from "./Detail";
// 만든 페이지들 가져오기!
function App() {
const days = ["월", "화", "수", "목", "금", "토", "일"];
//모든 페이지에서 사용될 값들을 만들어서, 아래에서 props로 보내줌!
return (
<div className="App">
<Container>
{/* 담을 container 만들어서 컴포넌트들(페이지들) 담기 */}
<Route path="/" exact>
{/* Route로 감싸는데 path="" 작성,(메인은 주로 /), exact로 완전히 같을 때만 보여줘! (exact 없을경우 포함하면 다 보여줘) */}
<Main days={days} />
{/* 컴포넌트(페이지) 넣어주기, 넣어줄 때 props 넘겨줄 수 있음. props이름은 내마음대로 작성! */}
</Route>
<Route path="/detail/:id" exact>
{/* path에 /:id로 파라미터 전송가능!
파라미터 보내는 페이지에서는 <Link to={`/detail/${id}`}> 이런식으로 넣어줌!
파라미터는 데이터를 받을 페이지에서 useParams를 리액트-라우터-돔으로 임포트해서 사용! */}
<Detail days={days} />
</Route>
</Container>
</div>
);
}
export default App;
// index.js에서 받아야 하므로 export default 필수!
*컴포넌트를 다 함수로 만들어서 const 000 = () => {return()} -> container에 컴포넌트를 담은다음(컨테이너도 함수로,컴포넌트 첫글자 대문자로!)
-> App에 넣어줌
————————————————————————————————————————————————————————————————————————————————————————————————
<3. 컴포넌트(페이지) 만들기>
import React from "react";
import styled from "styled-components";
const Page= (props) => {
return
export default Page;
———————————————————————————————————————————————————————
<잘못된 주소 처리하기>
exact로 중복 주소를 처리하는 방법은 이미 배웠습니다! 이번엔 우리가 미리 정하지 않은 주소로 들어온 경우를 다뤄볼게요.
(1) 일단 NotFound.js 파일을 만들고 빈 컴포넌트를 만들어주세요.
import React from "react";
const NotFound = (props) => {
return
export default NotFound;
(2)App.js에서 불러옵니다.
(3)Switch를 추가해주고,
import { Route, Switch } from "react-router-dom";
(4)NotFound컴포넌트를 Route에 주소 없이 연결하면 끝!
<Route
path="/"
exact
render={(props) => }
/>
(추가) 뒤로가기버튼 - NotFound.js에 추가
import React from "react";
import { useHistory } from "react-router-dom";
const NotFound = (props) => {
const history = useHistory();
return (
<>
<h1>주소가 올바르지 않아요!</h1>
<button
onClick={() => {
history.push("/");
}}
>
뒤로가기
</button>
</>
);
};
———————————————————————————————————————————————————————
3. State 관리
———————————————————————————————————————————————————————
useState 훅을 통해서 관리 가능!
const [data, data를 변경시킬함수] = React.useState(초기값(0 or "" or [])); -> useState 이용해서 계속 변화하는 평균값 넣어줌
Ex) const [avg, setAvg] = React.useState(avgNum.toFixed(1));
// avg로 data지정, 변경시킬 함수는 주로 data 앞에 set을 붙임 setAvg/ React.useState로 훅 사용/초기값은 지금 화면의 값들의 평균값인 avgNum넣고 .toFixed(1)로 소수점 아래 1자리까지 출력!
Ex) const reset = () => setAvg(0.0);
//버튼 누르면 실행될 reset함수/ setAvg(0.0)으로 바꿔줌! -> 이런 식으로 함수로 불러와서 값 변경해줌!
————————————————————————————————————————————————————————————————————————————————————————————————
1.
function App() {
const [counter, modifier] = React.useState(0);
// [date, data를 변경시킬 함수]
const Title = () => {
return
다음 data를 변경시킬 함수를 만들어줌
function App() {
const [counter, setCounter] = React.useState(0); //주로 modifier라 안하고 set을 붙여줌 data에
// [date, data를 변경시킬 함수]
const onClick = () => {
//setCounter(counter + 1); //data에 변경값주고
setCounter((current)=>current + 1);
};
const Title = () => {
return
이러면 자동 리렌더링까지 해줌!
<state값 변경해주기>
———————————————————————————————————————————————————————
4. 페이지 이동
———————————————————————————————————————————————————————
<history 이용하기>
import { useHistory } from "react-router-dom";
// useHistory 사용위해 임포트
컴포넌트 안에
const history = useHistory();
//.history로 바로 사용가능하게
사용할 곳에 불러와서 사용
<button onClick={()=>history.push(“/”)}>
———————————————————————————————————————————————————————
5. Props 받기
———————————————————————————————————————————————————————
페이지 시작할 때 받아옴
const Main = (props) => {
const days_list = props.days;
// 받아온 데이터를 알맞게 이름지어서 사용!
return null;};
———————————————————————————————————————————————————————
function App() {
const MainBtn = (props) => { //2. props를 넣어 props.이름해서 꺼내 쓰거나
return {props.text}; //props대신 {이름}을 넣어 바로사용가능, {이름1,이름2}여러개 사용가능
};
return (
<div className="App">
<MainBtn text="Save Changes" big={true} /> //1. props를 만든다. 원하는 이름으로 몇개를 만들든 props에 담긴다.
<MainBtn text="Continue" big={false} />
</div>
);
}
const Btn = styled.button background-color: tomato; color: white; padding: 10px 20px; border: 0; border-radius: 10px;
;
———————————————————————————————————————————————————————
6. .map()으로 나열하기
———————————————————————————————————————————————————————
{/ 나열해주기 리스트 /}
<ul>
{toDos.map((item, index) => (
//2. 그래서 index를 추가해줌, item 주면서 번호붙여서줌!
<li key={index}>{item}</li>
// 1. item에 key를 넣어줘야함!
))}
</ul>
———————————————————————————————————————————————————————
내 일주일은? {days_list.map((list, id) => { //.map((item, index)=>{———————————————————————————————————————————————————————
7. 파라미터 값 보내고 받기
———————————————————————————————————————————————————————
<1. App.js에서 미리 어떤이름으로 보낼지 정해줌>
{/* path에 /:id로 파라미터 전송가능!
<2. 보내는 페이지에서 >
<Link to={`/detail/${id}`}>
{/* 링크를 이용하여 세모 눌렀을 때 id값 파라미터로 주면서 /detail로 이동 */}
<Triangle></Triangle>
</Link>
<3. 받는페이지에서>
import { Link, useParams } from "react-router-dom";
//파라미터는 데이터를 받을 페이지에서 useParams를 리액트-라우터-돔으로 임포트해서 사용! */}
const Detail = (props) => {
const { id } = useParams();
// useParams 훅으로 파라미터 값인 id값 받아옴!
이런식으로 사용
<h3>
<Day>{props.days[id]}요일</Day> 평점 남기기
{/* 받아온 파라미터로 몇번째인지 알 수 있고, 그걸 통해 props에 .days에 무슨 요일인지 알 수 있음! */}
</h3>
———————————————————————————————————————————————————————
8. Input과 state
———————————————————————————————————————————————————————
function App() {
const [minutes, setMinutes] = React.useState();
const onChange = (event) => { //3.event추가 -> 이벤트 발생시
setMinutes(event.target.value); // 4. 입력된 값으로 변화
};
const Container = () => {
return (
<div>
<Title />
<label htmlFor="minutes">Minutes</label>
<input
value={minutes} //1.값을 minutes로
id="minutes"
type="number"
placeholder="Minutes"
onChange={onChange} //2. onChange를 통해 변화를 감지해서
></input>
</div>
);
};
return (
<div className="App">
<Container />
</div>
);
}
———————————————————————————————————————————————————————
두 개의 argument를 가지는 함수
첫 번째 argument는 우리가 딱 한번만 실행하고 싶은 코드
두 번째는 [] 배열을 넣어줌
-> useEffect가 컴포넌트의 첫 번째 렌더 시점에 iRunOnlyOnce 함수 호출
그리고 상태를 변화시키면 iRunOnlyOnce는 호출되지 않음
즉, 한번만 렌더링 됨
단순화 하여 useEffect(() => {
console.log("CALL THE API")
},[]); 써도 됨
-> []를 지켜봐라인데 지켜볼게 없어서 한번만 실행됨.
만약
useEffect(() => {
if (keyword !== "" && keyword.length > 5) { // 조건도 추가해줄수 있다. 만약 keyword가 빈칸이아니고 길이가 5이상 일때
console.log("SEARCH FOR", keyword);
}
}, [keyword]);
-> keyword가 변화할때만 실행됨.
———————————————————————————————————————————————————————
10. EventListner
———————————————————————————————————————————————————————
이벤트 리스너는 사용자가 어떤 행동(=이벤트)을 하는 지 아닌 지 지켜보다가 알려주는 것입니다.
대표적으로는 마우스 클릭, 터치, 마우스 오버, 키보드 누름 등이 자주 쓰여요!
getElementby~~로 요소 잡아와서 addEventListener달아주자! ref로 데리고 와서 addEventListener 달아줌!
addEventListener를 사용하려면 dom요소까지 완성이 되어 있어야함. 따라서 마운트가 끝나야함. 고로 DidMount에 넣음
만든 이벤트리스너는 컴포넌트가 사라질 때 함께 사라져야함! WillUnmonut에서 제거해주자
<클래스형 컴포넌트에서 Event Listener>
class App extends React.Component {
constructor(props) {
super(props);
this.state = {};
this.circle = React.createRef(null); //1. Ref로 요소 가져옴
}
//2. 이벤트 함수 작성
hoverEvent = (e) => {
//이벤트를 파라미터로 받아온다
console.log(e.target); //이벤트가 발생한 요소를 가져옴
console.log(this.circle.current);
this.circle.current.style.background = "yellow"; //4. 바꿀 변경사항 작성
};
componentDidMount() {
console.log(this.circle);
//3. addEventListener를 사용하려면 dom요소까지 완성이 되어 있어야함. 따라서 마운트가 끝나야함. 고로 DidMount에 넣음
// this.circle.current.addEventListener(어떤이벤트, 어떤행동할게)
this.circle.current.addEventListener("mouseover", this.hoverEvent);
}
//5. 컴포넌트 사라질때 이벤트리스너도 같이 지워져야함!
componentWillUnmount() {
this.circle.current.removeEventListener("moserover", this.hoverEvent);
}
render() {
return (
<div style={{ width: "100vw", height: "100vh", textAlign: "center" }}>
<Text />
<div
style={{
margin: "auto",
width: "250px",
height: "250px",
background: "green",
borderRadius: "250px",
}}
ref={this.circle}
></div>
</div>
);
}
}
<함수형 컴포넌트에서 Event Listener>
const Text = (props) => {
const text = React.useRef(null);
const hoverEvent = () => {
//2. 이벤트 함수생성
text.current.style.background = "yellow";
};
//리액트 훅 중에 하나! DidMount, DidUpdate,WillunMount 세개를 합쳐준 것
//컴포넌트가 렌더링 되면 화살표 함수를 실행 ()=>{} /첫번째 실행은 무조건 실행됨. 두번째 실행부터는 뒤에 [Dependency Array]의 요소를 확인해서 바뀐게 있다면 실행
//1. useEffect훅 만들어주기
React.useEffect(() => {
text.current.addEventListener("mouseover", hoverEvent); //3.이벤트리스너 넣기
//4. useEffect 안에서 리턴이 WillunMount 역할
return () => {
text.current.removeEventListener("mouseover", hoverEvent);
};
}, []);
return
const Wrap = styled.div`
display: flex;
flex-direction: column;
height: 100%;
overflow-x: hidden;
overflow-y: auto;
.button {
으로 내부에 것도 가능!
};
`;
———————————————————————————————————————————————————————
클래스형 컴포넌트
———————————————————————————————————————————————————————
클래스형 컴포넌트 생성 순서
1. import React from “react”;
class App extends React.Component {}
class App extends React.Component {
render (){
return ()
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render (){
return ()
}
}
——————————————————
21) 클래스형 컴포넌트에서 state 관리 - setState()
import React from "react";
class App extends React.Component {
constructor(props) {
super(props);
this.state = { //네모 초기 개수 설정
count: 3,
};
}
componentDidMount() {}
addNemo = () => {
this.setState({ count: this.state.count + 1 }); // setState()로 컴포넌트의 state값 업데이트(같은 형식으로 딕셔너리형이여서 똑같이 함)
};
removeNemo = () => {
if (this.state.count > 0) {
this.setState({ count: this.state.count - 1 });
} else {
window.alert("네모가 없어요!");
}
}; //렌더 위에서 네모추가 함수 작성
render() {
const nemo_count = Array.from({ length: this.state.count }, (v, i) => i);
return (
<div className="App">
{nemo_count.map((n, i) => {
return (
<div
key={i}
style={{
width: "150px",
height: "150px",
backgroundColor: "#ddd",
margin: "10px",
}}
>
nemo
</div>
);
})}
<div>
<button onClick={this.addNemo}>하나 추가</button> // onClick={} 해서 this.함수 넣어주기,but ()붙이면 즉시실행됨.
<button onClick={this.removeNemo}>하나 빼기</button>
</div>
</div>
);
}
}
export default App;