Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

Kimyeongkyung

react 기초 문법 정리 본문

카테고리 없음

react 기초 문법 정리

yeongk0825 2022. 3. 23. 01:40

 

0123

※함수 표현식 & 화살표 함수

1) 함수 표현식

let do_something = function [함수 이름]( ){ ... }

 

2) 화살표 함수(함수 표현식의 단축형)

let do_something = ( ) => { ... }

 

class Cat{

constructor(어디선가 받아오는 값 A) {

생성자 함수

      this.name= A;

      나 자신을 가리키는 키워드

// 어디선가 받아오는 값을 Cat이라는 함수에 넣어주겠다 

}

 

let cat = new Cat("B");//Cat이라는 클래스를 사용해서 새로운 객체를 만드는 키워드//B는 name

cat.showName( );

출력 => B

 

상속

class MyCat entends Cat{

//A라는 class를 만들건데 A는 Cat이라는 class를 확장해 올거야

     constructor(name,age){

     //name은 이미 위에 부모 class에 값이 있으니까 this~ 써줄필요 없이 super라는 함수를 써서 가져오자. 일단 부모 class에 접근!

          super(name);           this.age =  age;    }          showName(){                 console.log(this.name + "입니다");          }}let my_cat  = new MyCat("B", 4); //name, age

my_cat.showAge();

출력 : 4

 

my_cat.showName();

출력 : B입니다 

//class 이름이 같을 경우 자식클래스에 있는 친구를 우선적으로 가져다 쓰기 때문

 

※묵시적 형변환

 

1(숫자) + "2"(문자)출력 : "12"(문자)

 

※ = / = = /= = =

1) =

:어떤 변수에 값을 할당할 때 사용

 

2) = =

:등차. 유형(숫자, 문자열..)을 비교하지 않음. 변수 값을 기반으로 비교

ex) 0 = = "0" 은 true 

 

3) = = =

: 유형까지 비교하는 등차.

ex) 1 = = "1" 은 false

 

※ spread 문법

: 딕셔너리(key,value)나 배열([ ])에 어떤 요소가 들어가 있는데 그 요소들을 전부 객체 바깥으로 끄집어내줌

ex) let a1=[1,2,3]

     let a2=[4,5,6]

     let a3=[...a1, ...a2]

     => a3 = [1,2,3,4,5,6]

 

삼항 연산

: 조건 ? true 출력 or true면 실행할 행동 : false 출력 or false면 실행할 행동

 

let is= 5;

let e = is === 5 ? 3 : 4;

 

※ JSX 사용법

 

 

※ Array 내장 함수

1)map

: 어디까지 반복할 건지 끝 값을 정해줘야 하는 for문과 달리 map은 알아서 끝까지 돌려줌

const array_num = [0,1,2,3,4,5];
const new_array = array_num.map((array_item)=> {
	return array_item + 1; //요소요소들에게 +1을 해준다
})

console.log(new_array);

출력 : [1,2,3,4,5,6]

//원본 배열
console.log(array_num);

출력 : [0,1,2,3,4,5]
//원본 배열에 영향을 주지 않고 새로운 배열을 만들어냄

 

2)filter

: 어떤 조건을 만족하는 항목들만 골라서 새로운 배열을 만들어주는 것 

const array_num = [0,1,2,3,4,5]
const new_array = array_num.filter((array_item) => {
	return array_item > 3; //배열에서 3보다 큰 값만 골라내줘
})

console.log(new_array);

//map은 요소에 가공을 할 수 있었다면 filter는 요소 자체를 가공할 수는 없지만
요소들 중 어떤 조건을 만족하는 애들만 찾아낼 때 사용

 

3)concat

: 두 array를 합쳐주고 싶을 때 사용. 중복 제거는 해주지 않는다!

const array_num = [0,1,2,3,4,5]
const new_array = [4,5]

const merge = array_num.concat(new_array) //두 배열을 합쳐줘

console.log(merge);

출력:[0,1,2,3,4,5,4,5]

 

4)from

map, filter와 같은 내장함수를 사용할 수 없는 유사배열을 배열로 만들어줄 때, 배열에 들어갈 요소가 확실하지 않지만 길이가 a인 배열을 만들고 싶을때 사용

const my_name="sparta";

const my_name_array = Array.from(my_name);

console.log(my_name_array);

출력: ["s","p","a","r","t","a"];
//문자열을 구성하고 있는 하나하나가 배열의 한 요소가 됨.

...

근데 만약 저 배열을 숫자로 출력하고 싶다면?

...

const my_name="sparta";

const num_array = Array.from(my_name, (item,index) => {return index});
//(item, index) 
//(값, 콜백함수(배열 안 각각의 항목))

console.log(num_array)

출력:[0,1,2,3,4,5]
//---------------------------------------------------------------------

//길이가 a인 배열
const new_array = Array.from({length:4},(item, index) => {
	return index;
};

console.log(new_array);

출력:[0,1,2,3]

 

내장 함수 응용해보기

const animals = ["강아지", "고양이", "햄스터", "강아지", "고양이", "고양이", "토끼"];

animals.map((animal) => {
    if(animal === "고양이"){ //고양이가 있으면 count 1 증가시켜줘
        count += 1;
    }
});

console.log(count); //총 count는?

출력 : 3

-----------------------------------------------------------------------------------------
const animals = ["복슬 강아지", "검정 고양이", "노란 햄스터", "강아지", "노랑 고양이", "고양이", "흰 토끼"];

let cats = animals.filter((animal)=>{
    return animal.indexOf("고양이") !== -1;
    //-1을 쓴 이유? "고양이가 배열안에 들어있지 않다" = 위치가 없다.
    // !==을 사용해 고양이라는 단어가 포함된 원소만 찾기 
});

console.log(cats);
출력 : ['검정 고양이', '노랑 고양이', '고양이']

 

문자열의 내장함수 목록 참고링크

https://codedragon.tistory.com/9884

 

문자열 내장함수, 문자열 내장함수들

문자열 내장함수 ·       문자열 자료형이 자체적으로 가지고 있는 함수입니다. ·       문자열 내장함수를 사용하기 위해서는 문자열 변수 이름 뒤에 점(.)를 붙인 다음에 사용하고자 하

codedragon.tistory.com

 

JSX 사용법

: HTML을 품은 자바스크립트

  • dictionary : (key,value)로 이루어진 자바스크립트 자료형 중 하나

        => JSX 안에서 자바립트 변수나 어떤것을 쓰려면 중괄호 필수

  • Style을 줄때도 마찬가지로 그냥 string으로 dictionary(객체) 로 넘겨주어야 하기 때문에 이중 중괄호 필요

        => style = {{ 스타일 속성= "", 스타일 속성 = ""...}}

 

라이프 사이클 알아보기=> 컴포넌트가 웹페이지에 들어갔다가 사라지기까지의 한 과정.

클래스형 컴포넌트에서만 사용.

함수형 컴포넌트에서는 라이프 사이클을 사용할 수 없기 때문에(constructor에 값을 넣어 초기화를 해줄수가 없다는 뜻!)

리액트 훅을 사용하고,

 

 

1) DOM : HTML 단위(요소) 하나하나를 객체 취급하는 모델. 트리구조!

 

2) 가상 DOM:눈에 보이지 않는 메모리상에서 돌아가는 가짜 DOM. 

 

어떻게 돌아가?

어떤 행동을 하면(변화) 일단 가상 DOM에 올려(새로 그리기) → 진짜 DOM과 비교 →  바뀐부분만 마지막에 진짜          DOM에 반영

 

진짜 DOM과 가상 DOM을 비교할 때 뭐가 바뀐지 어떻게 알지?

=>그래서 비교를 하기 위해서는 key값이 필요하다!

 

 

생성 → 업데이트 → 제거

 

constructor(생성자 함수) : 컴포넌트에 필요한 어떤 값을 넣어주는 것

 

render : 변경된 내용이 가상 DOM 에서 진짜 DOM으로 올라가는 과정. 

  • New props : 부모가 자식에서 주는 데이터가 바뀌었을 때
  • setState() : 내가 가진 데이터가 바뀌었을 때
  • forceUpdate : 강제로 업데이트 일으킴(강제 수정)
  • 부모 컴포넌트가 업데이트 되었을 때

나 이제 바뀔꺼야! 근데 뭘로 바뀔거야?

=>render 안 return 안에 넣어주기

(Mount는 끝난 상태임)

 

componentDidMount : render가 끝났을때(진짜 DOM에 잘 붙었을 때)

: 첫번째 렌더링이 끝난 후 진짜 DOM에 올라간 뒤 딱 한번만 실행됨. 업데이트(리렌더링) 시에는 실행되지 않음

  • 돔 관련 처리 가능

 

componentDidUpdate : 나 변경사항 업데이트 됐어! (리렌더링)

: 리렌더링이 끝난 후 호출됨( 이미 가상 DOM이 실제 DOM으로 올라간 뒤)

  • componentDidUpdate(prevProps, prevState)

                                                       업데이트 되기 전의 prop(부모가 준 거)와 state(내 꺼)

  • 돔 관련 처리 가능

componentWillUnmount : 나 이제 사라진다!

 

 2)그럼 진짜 DOM은 언제 새로 그리지?

  • 처음 페이지 진입 시
  • 데이터가 변해서 마지막에 가상돔에서 변경된 부분이 적용될 때

왜 진짜 DOM에 바로 변경사항을 적용 안해? 그렇게 느려?=> 사이트 구조에 따라서 가상 DOM을 쓰는 것보다 진짜 DOM을 직접 만지는게 더 빠를수도! 아니면 더 느릴수도!

 

 

 

props : 부모 컴포넌트. state가 props로부터 데이터를 받아올 경우 변경이 불가능함

state : 생성, 수정이 해당 컴포넌트 내에서만 이루어짐. 그래서 생성도 수정도 자유로움

 

※다른 파일에 있는 컴포넌트 불러오기

 

<Bucketlist.js>

import React from "react"; 

const BucketList = (props) => {

}

//파라미터로 들어온 값은 dictonary 형태임.

//받아온 key값이 list인 무언가가 있는데 이 list에 담긴 어떤 값은 받아온 것이다!
//props, props.list 로 써도 무방함

const BucketList = ( {list} ) => {
  const my_lists = list;
}

export default Bucketlist;

(= export {BucketList}; 로 쓸수도 있음)

 

클래스형 <App.js>

import React from "react"; 
import Bucketlist from "./BucketList";

class App extends React.Component{
  constructor(props){
      super(props);
      this.state = {
           list=["a", "b", "c"],
  };
}
    render(){
    	return (
        	<div className = "App">
            	<BucketList  list={this.state.list}/>
        	</div>
    	)
	}
}

export default App;
//return되는 값은 무조건 1개 이상 필요하다(null을 넣더라도 꼭!)

 

함수형<App.js>

import Bucketlist from "./BucketList";
(= import {Bucketlist} from "./BucketList"로 쓸수도 있음)

function App(){
  return(
      <div className = "App">
          <BucketList />
      </div>
  );
}

export default App;

 

styled-components

: 컴포넌트에 직접적으로 스타일을 입히는 방식

 

1) 패키지 설치

 yarn add styled-components

 

2) 사용해보기

<App.js>

import React from "react";
import Bucketlist from "./BucketList";

class App extends React.Component{
      constructor(props){
      super(props);
        this.state = {
           list=["a", "b", "c"],
    };
}
render(){
    //return되는 값은 무조건 1개이상 필요하다(null을 넣더라도 꼭!)
        return (
        <div className = "App">
            <MyStyled bg_color={"red"}/>
            <BucketList  list={this.state.list}/>
        </div>
        )	
    }
const MyStyled = styled.div`

   원하는 스타일 작성 후 render 안에 <MyStyled/> 추가해주기
   background-color : ${(props) => (props.bg_color)};
     //축약 전 코드 : ${(props) => { return props.bg_color }};
     //prop로 받아온 것중에 bg_color로 받아온거 꺼내줘

`

export default App;

 

SCSS에서 자주쓰는 문법

 

1. nesting

 : sccs에서는 반복되는 써야하는 걸 한 묶음으로 묶을 수 있음. <MyStyled> 태그 안에 속해있는 <p>태그에 스타일을 주고 싶을때( 각각 styled 객체를 만들 필요가 없음)

 

<BucketList.js>

<div className = "App">

<MyStyled>
<p></p>
<MyStyled/>
    <BucketList  list={this.state.list}/>
</div>

const MyStyled = styled.div`
p{
  원하는 p태그의 스타일 작성
  }
`

 

2. &은 자기 자신 지칭!

 

const MyStyled = styled.div`

&:hover( 등의 마우스이벤트 ){

   원하는 스타일 작성

}

 

createRef

: 클래스형 함수에서 리액트 요소를 가져올 수 있는 방법 중 하나(=이름표). 라이프사이클 메서드임.

 

import React from "react";

import Bucketlist from "./BucketList";

 

class App extends React.Component{

  constructor(props){

    super(props);

    this.state = {

       list=[''a", "b", "c"],

    };

    this.text = React.createRef( ); //나 ref 만들어서 text로 가져올거야

}

componentDidMount(){

   console.log(this.text);

} //마운트 완료

render(){

//return되는 값은 무조건 1개이상 필요하다(null을 넣더라도 꼭!)

return (

<div>

    <input type ="text" ref={this.text} onChange = {()=> {console.log(this.text.current.value);}}/> //로 확인가능

</div>

)

}

useRef

:함수형 컴포넌트에서는 라이프 사이클메서드를 사용할 수 없으므로(=constructor 안에서 무언가를 초기화 할 수 없다)

createRef 대신 리액트 훅 

 

// 변수를 만든다.

const my_wrap = React.useRef(초기값);

 

return (

<div ref={my_wrap}>

  {my_lists.map((list,index)=> {

    return <ItemStyle key={index}>{list}</ItemStyle>;

});

)

 

state 관리

 

import React from "react";

import Bucketlist from "./BucketList";

 

class App extends React.Component{

  constructor(props){

    super(props);

    this.state = {count:3,};

}}

//count 숫자를 가지고 배열을 만들고, 그 배열만큼 map을 돌려줘야함

component Didmount(){

}

render(){

return (

<div className = "App">

  <div style = {{

     width:'150px',

     height:'150px',

     backgroundColor:'#ddd',

 

}}>

nemo

)}

 

(1)새 프로젝트 만들기

yarn create react-app nemo

 

(2) App.js를 class형 컴포넌트로 바꾸고 시작!

// App component를 class형으로!

 

import React from 'react'; class App extends React.Component { constructor(props){ super(props);

this.state = {} } componentDidMount(){ }

 

render(){ return ( <div className="App"> </div> ); } }

export default App;

 

(3) state에 count라는 변수를 추가하고, count 숫자만큼 네모칸을 화면에 띄우기

 

(4) 더하기, 빼기 버튼을 만들고,

return (

<div className="App"> {nemo_count.map((num, idx) => {

 

  return (

  <div key={idx}

   style={{ width: "150px", height: "150px", backgroundColor: "#ddd", margin: "10px", }} > nemo</div>   ); })}

   <div>

   <button>하나 추가</button>

   <button>하나 빼기</button>

   </div>

     </div> );

(5) 함수를 만들어서

addNemo = () => { // this.setState로 count를 하나 더해줍니다!

 

this.setState({ count: this.state.count + 1 }); }; removeNemo = () => {

// 네모 갯수가 0보다 작을 순 없겠죠! if문으로 조건을 걸어줍시다.

if (this.state.count > 0) { // this.setState로 count를 하나 빼줍니다!

this.setState({ count: this.state.count - 1 }); }else{ window.alert('네모가 없어요!'); } };

 

(6) 연결하자!

return (

<div className="App"> {nemo_count.map((num, idx) => {

return ( <div key={idx} style={{

width: "150px", height: "150px", backgroundColor: "#ddd", margin: "10px", }} >

nemo </div> ); })} <div> {/* 함수를 호출합니다. 이 클래스 안의 addNemo 함수를 불러오기 때문에 this.addNemo로 표기해요. */} <button onClick={this.addNemo}>하나 추가</button> <button onClick={this.removeNemo}>하나 빼기</button> </div> </div> );

 

Ref

우리가 코드에서 다루는 요소는 리액트 요소!

예를들어 input에 무언가을 쓰고 카드를 만들어서 붙인다?

자바스크립트로는 가능하지만 리액트에서는 약간 찝찝한 느낌

 

input이 없던 페이지에 input을 만들거야!

일단 가상DOM에 input을 추가하고, 이 input을 찾기 위해

getElementById~~를 한다? NO!!!!!!!! 진짜 DOM에는 현재 input이 없기 때문에 오류가 나게됨

 

그럼 리액트에서는 변경사항이 적용된 가상 DOM(예를 들어 input의 text)을 어떻게 가져오지?

import React from "react";
import styled from "styled-components";

// 함수형 컴포넌트는 이렇게 쓸 수도 있고
//const BucketSecond = (props) => {
// console.log(props);
// return (
//  <div>버킷 리스트</div>
// );
// }

//{list}:어떤값은 받아온 것
const BucketSecond = ({ list }) => {
    const my_lists = list;
    const my_wrap = React.useRef(null);

    window.setTimeout(()=>{
        console.log(my_wrap);
    },1000); //1초 있다가 첫번째 인자에 넣은 함수를 실행하도록 해
    
    return (
        <div ref={my_wrap}>
            {my_lists.map((list, index) => {
                    // console.log(list);
                    
                    return (
                        <ItemStyle className="list-item" key={index}>
                            {list}
                        </ItemStyle>
                    );
                })
            }
        </div>
    );
};

※ eventlistener

: <div onClick = {}>처럼 직접 element에 이벤트를 넣어줄 수 있지만, addEventListener를 통해 이벤트를 넣을 수도 있다!

 

 

state와 props 간의 데이터 교환이 잘 이루어짐.

근데 만약 컴포넌트가 많아진다면?

형제관계(sibling) 끼리는 데이터 교환이 불가능..저~아래 자식컴포넌트한테 데이터를 전달해줘야 할때..

 

방법은 리덕스!

리덕스

 

라우팅

MPA : HTML이 여러개

SPA : HTML이 딱 하나

페이지를 이동할 때마다 서버는 클라이언트에게 HTML을 주는데

왜 우리는 SPA를 사용하지?

 

모든 페이지가 다 완전히 다른 뷰를 가지고 있나?

NO!!!

 

header와 footer는 페이지마다 같다.

만약 MPA를 사용하면 페이지가 이동될때마다 진짜 DOM → 진짜 DOM으로 갈아치우는 과정에서

필요하지 않은 작업을 많이 하게됨(안바뀌는 부분까지 매번 바뀌어버림)

또한 매번 새로고침될때마다 페이지가 바뀌기 때문에 상태값 유지가 안됨

(예를 들어 회원가입 시 쓰고있던 정보가 날라가는 상황 초래)

 

그럼 SPA는 단점이 없어?

 

유저가 홈페이지를 방문할때 회원가입을 할지 안할지 모름

회원가입 페이지를 들어갈지 안들어갈지 모른다는뜻

하지만 SPA는 처음부터 모든페이지를 서버로부터 다 받아오기 때문에

첫 로딩시간이 굉장히 느릴 수 있다. 

하지만 페이지 간 이동은 이미 모든페이지를 받아온 상태이기 때문에 매우빠름!

 

한 HTML 안에서 A, B페이지에 필요한 컴포넌트를 각각 묶고, 보여주는 과정을 직접 구현하긴 어려우니까

그걸 도와주는 게 라우팅 라이브러리!

 

yarn add react-router-dom 설치

 

URL 파라미터( & 쿼리)

사용자가 어떤 페이지에서 글을 작성했다. 이 글이 뭔지 알아채서 매번 라우터에 추가해줘야 할까?

 

NO!

 

URL 파라미터를 통해 똑같은 뷰에 안에있는 데이터만 갈아끼우는 형식으로 사용!

 

<app.js>

1. useParams 사용하기

/cat/: 변수명(어떤 변수명으로 받아올건지)

import {Route, Link} from "react-router-dom";
import Home from "./Home";
import Dog from "./Dog";
import Cat from "./Cat";

//pate ="/" => /포함하면 메인까지 다보여줘라. exact 추가시 /와 /cat은 다르기 때문에 페이지 이동시 메인화면은 안보이게됨
// "cat/:cat_name" 파라미터로 받아오는 방법
// <Cat />

//props로 받아오는 방법
//<Cat /> 대신 component={Cat} 추가
function App() {
  return (
    <div className="App">
      <div>
        <Link to="/">Home으로 이동</Link>
        <Link to="/cat">Cat으로 이동</Link>
        <Link to="/dog">Dog으로 이동</Link>
      </div>
      <Route path ="/" exact> {/*완전히 똑같으면 보여줘 */}
        <Home />
      </Route>
      <Route path = "/cat/:cat_name" component={Cat}> 
        {/* <Cat /> */}
      </Route>
      <Route path ="/dog"> 
        <Dog />
      </Route>
    </div>
  );
}

export default App;

 

<Cat.js>

import React from "react";
import { useParams } from "react-router-dom";

const Cat = (props) => {
    const cat_name = useParams();

	//다른방법
    //자식 컴포넌트를 바로 넘겨주는 방법
    //App.js에서 Rount 경로 적는 라인에 component={Cat} 추가
    
    
    console.log(cat_name);
    return (<div>고양이 화면 입니다!</div>);
};

export default Cat;

 

그런데 매일 주소창에 /cat/이동할 페이지의 변수명 을 적어서 이동을 할 수는 없다!

 

 

<Link /> 사용해서 페이지 이동 링크 만들기

function App() {
  return (
    <div className="App">
      <div>
        <Link to="/">Home으로 이동</Link>
        <Link to="/cat">Cat으로 이동</Link>
        <Link to="/dog">Dog으로 이동</Link>
      </div>
      .
      .
  )
}

 

하지만 링크를 모든곳에 달아줄수는 없다. 이럴땐 어떡해?

 

history 사용해서 페이지 링크 만들기

import React from "react";
import {useHistory} from "react-router-dom";


const Dog = (props) => {
    const history = useHistory();
    console.log(props);
    return (<div onClick={()=>{
            history.push("/cat");
    }}>멍멍이 화면 입니다!</div>);

};

export default Dog;

 

페이지 주소가 잘못됐을 때

: 주소가 잘못된 경우 흰 화면만 뜨면 사용자 입장에서 사이트가 이상하다고 생각할 수 있기 때문에 흰 화면만 나오지 않도록 조치가 필요함

 

1. 잘못된 주소로 접근한 경우 주소가 잘못되었다는 텍스트를 통해 알린다.

2. useHistory를 router-dom에서 가져와서,  뒤로가기 버튼을 누르면 다시 뒤로 갈 수 있게 한다.

import React from "react";
import styled from "styled-components";
import {useHistory} from "react-router-dom";

const NotFound = (props) => {
    const history = useHistory(); //나 history 갖다쓴다
    return (
        <>
        <h1>주소가 올바르지 않아요!</h1>
        <Button onClick={()=>{history.goBack();}}>뒤로 가기</Button>
        </>
    );
};

const Button = styled.div`
    width:200px;
    height:50px;
    background-color:#e67a65;
    border-radius:10px;
    font:bold 20px/50px arial;
    text-align:center;
    color:#fff;
    
`
export default NotFound;

 

Switch

: 위와 같이 주소가 잘못된 경우 나올 페이지를 지정해줄때 <App.js>에서 Switch문을 사용한다.

import React from "react";
import styled from "styled-components";
import { Route,Switch } from "react-router-dom";

// BucketList 컴포넌트를 import 해옵니다.
// import [컴포넌트 명] from [컴포넌트가 있는 파일경로];
import BucketSecond from "./BucketSecond";
import Detail from "./Detail";
import NotFound from "./NotFound";

function App() {

  const [list, setList] = React.useState(["주니어 개발자로 취업하기", "매일 책읽기", "수영 배우기"]);
  const text = React.useRef(null);

  const addBucketList = () => {
    // 스프레드 문법! 기억하고 계신가요? :) 
    // 원본 배열 list에 새로운 요소를 추가해주었습니다.
    setList([...list, text.current.value]);
  }

  console.log(list);
  return (
    <div className="App">
      <Container>
        <Title>내 버킷리스트</Title>
        <Line />
        {/* 컴포넌트를 넣어줍니다. */}
        {/* <컴포넌트 명 [props 명]={넘겨줄 것(리스트, 문자열, 숫자, ...)}/> */}

        <Switch>
            <Route path="/" exact>
            <BucketSecond list ={list} />
            </Route>
            <Route path="/Detail" component={Detail}>
                <Detail />
            </Route>
            <Route>
                <NotFound />
            </Route>
        </Switch>

      </Container>
      {/* 인풋박스와 추가하기 버튼을 넣어줬어요. */}
      <Input>
        <input type="text" ref={text} />
        <button onClick={addBucketList}>추가하기</button>
      </Input>
    </div>
  );
}

메인페이지와 서브페이지 이외의 다른 주소로 접근할 경우 NotFound 페이지로 이동하게 한다.

 

여기서 중요한 점은 NotFound.js를 마지막에 썼기때문에 이 페이지가 뜨는 것이아니라,

Switch문 안에서 NotFound.js 페이지가 path 지정이 안되어있기 때문에 이동이 가능한 것!

만약 Switch문이 없다면 모든페이지에서 NotFound가 나오게 됨

 

리덕스

: 전역상태를 관리해주는 패키지. 다른 프론트엔드 라이브러리에서도 사용 가능

 

1. 패키지 설치 

     yarn add redux react-redux(띄어쓰기로 한번에 여러개의 패키지를 설치할 수 있다)

                        -> 리덕스를 리액트에서 편하게 쓸 수 있게 도와주는 패키지

 

2. 리덕스 공식문서 : https://ko.redux.js.org/introduction/getting-started/

 

Redux 시작하기 | Redux

소개 > 시작하기: Redux를 배우고 사용하기 위한 자료

ko.redux.js.org

 

3. 상태관리 흐름

 

어떤 데이터가 있다. state라고 부른다.

이 state를 가져다 쓰는, 수정하려는 컴포넌트들이 꼭 있다.

컴포넌트들이 수정을 요청한다. 나 이거 이렇게 수정해줘!! = action을 dispatch 하다

=> ActionCreator : 액션을 만드는 함수(액션생성함수)

리액트에서도 state는 setState()나, useState() 훅을 써야만 변경이 가능함.

=> 데이터가 마구잡이로 변하지 않도록 불변성을 유지해주기 위함임.

 

불변성? 허락없이 데이터가 바뀌면 안된단 소리!

리덕스에 저장된 데이터 = 상태 = state는 읽기 전용

 

가지고 있던 값을 수정하지 않고, 새로운 값을 만들어서 상태를 갈아끼운다.

즉, A에 +1을 할 때, A = A+1이 되는 게 아니고, A' = A+1이라고 새로운 값을 만들고 A를 A'로 바꾼다는 뜻

 

ex) state=2; ( X ) 

     return 2; (o) => 직접적으로 리듀서를 건드리는 것이 아닌 새로운 값을 반환하는 것만 가능

 

리듀서에서 실제 수정이 이루어진다

state는 갖고있던 데이터가 바뀌었다. 나랑 연결되어있는 컴포넌트들에게 이 사실을 알려야한다.