✅ Event Listener
1️⃣ 이벤트 리스너란?
사용자가 어떤 행동(=이벤트)을 하는 지 아닌 지 지켜보다가 알려주는 것
ex) 마우스 클릭, 터치, 마우스 오버, 키보드 누름 등
이벤트 리스터는 <div, onClick = {} >에서처럼 엘리먼트에 직접 넣어줄 수도 있고 addEventListener를 통해 추가해볼 수도 있다.
👌 클래스형 컴포넌트에서 event listener 구독하기
🔹 이벤트 리스너의 위치
클릭을 하건, 마우스를 올리건 DOM 요소가 있어야 이벤트가 발생하는 지 지켜볼 수 있다.
즉, componentDidMount()에 넣어주면 된다.
▶️ 어떤 행동(= 이벤트 발생) 뒤에 실행할 함수 먼저 만들기
hoverEvent = (e) => { // 콘솔로 이 이벤트가 누구에게서 일어났는 지 확인할 수 있다. console.log(e.target); // ref랑 같은 건지 확인해보기 console.log(this.circle.current); this.circle.current.style.background = "yellow"; } |
▶️ 이제 addEventListener()를 이용해서 이벤트를 등록한다.
componentDidMount(){ // 리액트 요소가 잘 잡혔나 확인해보기 console.log(this.circle); // 마우스를 올렸을 때, 이벤트가 일어나는 지 확인해봅시다. this.circle.current.addEventListener("mouseover", this.hoverEvent); } |
▶️ 이벤트는 꼭 컴포넌트가 사라지면 지워줘야 한다.
🔹 이 과정을 clean up 이라고 부른다.
이벤트는 한번 등록되면 계속 남아있는데, 컴포넌트가 사라져도 이벤트가 실행되지 않을 뿐 남아는 있을 것이다.
그래서 깨끗하게 정돈해주는 과정이 필요한 것, 그것이 clean up
componentWillUnmount() { this.circle.current.removeEventListener("mouseover", this.hoverEvent); } |
👌 함수형 컴포넌트에서 event listener 구독하기
클릭을 하건, 마우스를 올리건 DOM 요소가 있어야 이벤트가 발생하는지 지켜볼 수 있다고 했다.
🔹 클래스형 컴포넌트에서는 componentDidMount()
🔹 함수형 컴포넌트에서는 componentDidMount()역할을 하는 useEffect() 훅을 쓴다.
❗ useEffect()
리액트 훅.
라이프 사이클 함수 중 componentDidMount와 componentDidUpdate, componentWillUnmount를 합쳐둔 것
// 화살표 함수! 렌더링 시 실행할 함수가 여기에 들어간다. // 두번째 인자의 []! 디펜던시 어레이라고 부른다. 여기 넣어준 값이 변하면 첫번째 인자인 콜백함수를 실행한다. React.useEffect(() => { // 여기가 rendering 때 실행될 구문이 들어가는 부분이다. // componentDidMount, componentDidUpdate일 때 동작하는 부분이 여기예요. // do something ... return () => { // 여기가 clean up 부분입니다. // componentWillUnmount 때 동작하는 부분이 여기예요. //do something ... }; }, []); |
▶️ 어떤 행동(=이벤트 발생!)뒤에 실행할 함수 먼저 만들기
const hoverEvent = (e) => { // 콘솔로 이 이벤트가 누구에게서 일어났는 지 확인할 수 있다. console.log(e.target); // ref랑 같은 건지 확인해보기 console.log(text.current); text.current.style.background = "yellow"; }; |
▶️ 이제 addEventListener()를 이용해서 이벤트 등록하기
// 화살표 함수! 렌더링 시 실행할 함수가 여기에 들어간다. // 두번째 인자의 []! 디펜던시 어레이라고 불러요. 여기 넣어준 값이 변하면 첫번째 인자인 콜백함수를 실행한다. React.useEffect(() => { // 여기가 rendering 때 실행될 구문이 들어가는 부분 // componentDidMount, componentDidUpdate일 때 동작하는 부분이 여기 text.current.addEventListener("mouseover", hoverEvent); return () => { // 여기가 clean up 부분입니다. // componentWillUnmount 때 동작하는 부분이 여기예요. //do something ... }; }, [text]); |
▶️ 이벤트는 꼭 컴포넌트가 사라지면 지워야한다.
❗ useEffect에서 clean up은 return 구문을 이용해서 한다.
React.useEffect(() => { text.current.addEventListener("mouseover", hoverEvent); return () => { // 여기가 clean up 부분입니다. // componentWillUnmount 때 동작하는 부분이 여기 text.current.removeEventListener("mouseover", hoverEvent); }; }, [text]); |
✅ 라우팅이란?
1️⃣ SPA란? Single Page Application
말 그대로 서버에서 주는 html이 1개 뿐인 어플리케이션
전통적인 웹사이트는 페이지를 이동할 때마다 서버에서 html, css, js(=정적자원들)을 내려준다면, SPA는 딱 한번만 정적자원을 받아온다.
👌 왜 굳이 html을 하나만 줄까?
많은 이유가 있으나, 그 중 제일 중요한 것은 사용성 때문이다.
페이지를 이동할 때마다 서버에서 주는 html로 화면을 바꾸다보면 상태 유지가 어렵고 바뀌지 않은 부분까지 새로 불러오니까 비효율적이다.
사용자가 회원가입하다가 적었던 내용이 날아갈 수도 있고 블로그같은 경우 페이지마다 새로 html을 받아오면 바뀐 건 글 뿐인데 헤더와 카테고리까지 전부 다시 불러와야 한다.
👌 단점은 없을까?
SPA는 딱 한 번 정적자원을 내려받다보니, 처음에 모든 컴포넌트를 받아온다.
즉, 사용자가 안들어가 볼 페이지까지 전부 가지고 온다. 특히 한 번에 전부 가지고 오기 때문에 아주 많은 컴포넌트가 있다면 첫 로딩 속도가 느려진다.
2️⃣ 라우팅이란?
👌 SPA는 주소를 어떻게 옮길 수 있을까?
html은 딱 하나만 가지고 있지만 SPA도 브라우저 주소창대로 다른 페이지를 보여줄 수 있다. 이렇게 브라우저 주소에 따라 다른 페이지를 보여주는 걸 라우팅이라고 한다.
✅ 리액트에서 라우팅 처리하기
1️⃣ 페이지 전환
👌 index.js에 BrowserRouter 적용하기
import React from 'react'; import ReactDOM from "react-dom"; import { BrowserRouter } from "react-router-dom"; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; // 이부분이 index.html에 있는 div#root에 우리가 만든 컴포넌트를 실제로 랜더링하도록 연결해주는 부분 ReactDOM.render( <BrowserRouter> <App /> </BrowserRouter>, document.getElementById("root") ); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals(); |
🔹 BrowserRouter(브라우저라우터)
웹 브라우저가 가지고 있는 주소 관련 정보를 props로 넘겨주는 기능
현재 내가 어느 주소를 보고 있는지 쉽게 알 수 있다.
👌세부 화면 만들기
Home.js
import React from "react"; const Home = (props) => { return ( <div>메인 화면이에요.</div> ) } export default Home; |
Cat.js
import React from "react"; const Cat = (props) => { return ( <div>고양이 화면이에요.</div> ) } export default Cat; |
Dog.js
import React from "react"; const Dog = (props) => { return ( <div>강아지 화면이에요.</div> ) } export default Dog; |
👌 App.js에서 Route 적용하기
🔹 Route 사용방법 1 : 넘겨줄 props가 없을 때
<Route path="주소[/home 처럼 /와 주소를 적어요]" component={[보여줄 컴포넌트]}/> |
🔹 Route 사용방법 2 : 넘겨줄 props가 있을 때(App.js에서 props로 넘겨주면, 이렇게 쓰면 된다)
ex) 버킷리스트 앱에서 list를 props로 넘겨주는 경우
<Route path="주소[/home 처럼 /와 주소를 적어요]" render={(props) => (<BucketList list={this.state.list} />)} /> |
import React from 'react'; import logo from './logo.svg'; import './App.css'; // Route를 먼저 불러와줍니다. import { Route } from "react-router-dom"; // 세부 페이지가 되어줄 컴포넌트들도 불러와주고요! import Home from "./Home"; import Cat from "./Cat"; import Dog from "./Dog"; class App extends React.Component { constructor(props){ super(props); this.state={}; } render(){ return ( <div className="App"> {/* 실제로 연결해볼까요! */} <Route path="/" component={Home} /> <Route path="/cat" component={Cat} /> <Route path="/dog" component={Dog} /> </div> ); } } export default App; |
👌 exact 적용하기
화면을 확인했을 때, /cat, /dog를 해도 Home 컴포넌트가 같이 나온다.
/cat, /dog에도 / 이 기호가 포함되어 있기 때문
<Route path="/" exact component={Home} /> <Route path="/cat" component={Cat} /> <Route path="/dog" component={Dog} /> </div> |
👌 URL 파라미터 사용하기
웹사이트 주소에는 파라미터와 쿼리라는 것이 있다.
🔹 파라미터 모양 :/cat/nabi
🔹 쿼리 :/cat?name=nabi
▶️ 파라미터 주는 방법
//App.js ... // 파라미터 주기 <Route path="/cat/:cat_name" component={Cat}/> ... |
▶️ 파라미터 사용 방법
//Cat.js import React from "react"; const Cat = (props) => { console.log(props.match); return ( <div>고양이 화면이에요.</div> ) } export default Cat; |
localhost:3000/cat/nabi 주소로 가서 console창을 확인해보면
이렇게 params가 {cat_name: "nabi"}로 나오는 것을 볼 수 있다.
👌 useParams 훅을 사용해서 이동하기
꼭 props에서 받아오지 않아도 useParams 훅을 사용하면 간단히 파라미터에 접근할 수 있다.
import React from "react"; import { useParams } from "react-router-dom"; const Cat = (props) => { const cat_name = useParams(); console.log(cat_name); // console.log(props); return ( <div>고양이 화면입니다!</div> ); }; export default Cat; |
👌 링크 이동 시키기
매번 주소창을 찍고 페이지를 돌아다닐 수 없기 대문에, react-router-dom 으로 페이지 이동하는 방법 살펴보기
🔹 <Link/> 사용하기
링크 컴포넌트는 html 중 a태그와 비슷한 역할을 하며, 리액트 내에서 페이지 전환을 도와준다.
<Link to="주소">[텍스트]</Link> |
▶️ App.js에 메뉴 넣기
// Route를 먼저 불러오고 // Link 컴포넌트도 불러오기 import { Route, Link } from "react-router-dom"; // 세부 페이지가 되어줄 컴포넌트들도 불러오기 import Home from "./Home"; import Cat from "./Cat"; import Dog from "./Dog"; 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" component={Cat}> {/* <Cat /> */} </Route> <Route path="/dog"> <Dog /> </Route> </div> ); } export default App; |
🔹 history 사용하기
▶️ props로 history 객체를 받아 이동하기
import React from "react"; const Dog = (props) => { // props의 history 객체를 살펴보기 console.log(props); // 그리고 history.push('/home')으로 페이지 이동 return ( <div onClick={() => { props.history.push("/home"); }} > 강아지 화면이에요. </div> ); }; export default Dog; |
▶️ useHistory 훅을 사용해서 이동하기
꼭 props에서 받아오지 않더라도 useHistory 훅을 사용하면 간단히 history 객체에 접근할 수 있다.
import React from "react"; import { useHistory } from "react-router-dom"; const Home = (props) => { let history = useHistory(); return ( <> <div>메인 화면이에요.</div> <button onClick={() => { history.push("/cat"); }} > cat으로 가기 </button> </> ); }; export default Home; |
✅ 라우팅, 꼼꼼하게 쓰는 법
1️⃣ 잘못된 주소 처리하기
exact로 중복 주소를 처리하는 방법은 위에 기재.( './' 와 './cat'처럼)
👌 우리가 먼저 정하지 않은 주소로 들어온 경우에 처리하는 법
🔹 NotFound.js 파일을 만들어서 빈 컴포넌트 만들기
import React from "react"; const NotFound = (props) => { return <h1>주소가 올바르지 않아요!</h1>; }; export default NotFound; |
🔹 App.js에서 불러오기
import NotFound from "./NotFound"; |
🔹 App.js에 Switch 추가하기
... import { Route, Switch } from "react-router-dom"; ... return ( <div className="App"> ... <Switch> <Route path="/" exact render={(props) => ( <BucketList list={this.state.list} history={this.props.history} /> )} /> <Route path="/detail" component={Detail} /> </Switch> ... </div> ); ... |
🔹 NotFound 컴포넌트를 Route에 주소 없이 연결하기
... <Switch> <Route path="/" exact render={(props) => ( <BucketList list={this.state.list} history={this.props.history} /> )} /> <Route path="/detail" component={Detail} /> <Route component={NotFound} /> </Switch> ... |
👌 <NotFound/>에 뒤로가기 버튼 달아보기
🔹 NotFound.js에 useHistroy를 가져오기
import { useHistory } from "react-router-dom"; |
🔹 버튼 만들어주기
import React from "react"; import { useHistory } from "react-router-dom"; const NotFound = (props) => { return ( <div> <h1>주소가 올바르지 않아요!</h1> <button>뒤로가기</button> </div> ); }; export default NotFound; |
🔹 useHistory를 사용해서 뒤로가기 만들기
import React from "react"; import { useHistory } from "react-router-dom"; const NotFound = (props) => { let history = useHistory(); return ( <div> <h1>주소가 올바르지 않아요!</h1> <button onClick={() => { history.goBack(); }} > 뒤로가기 </button> </div> ); }; export default NotFound; |
✅ 리덕스를 통한 리액트 상태관리
1️⃣ 상태관리가 필요한 이유
- 자식 컴포넌트는 부모 컴포넌트의 state를 마음대로 조작할 수 없다.
- 데이터는 부모에서 자식으로 흐르게 하기로 했기 때문, 데이터는 단방향으로!
만약 App컴포넌트와 AddListItem 컴포넌트가 같은 데이터 저장소를 본다면 ? AddListItem에서 추가를 하면 App이 보고 있는 데이터도 같이 추가 될 것.
리덕스는 여러 컴포넌트가 동일한 상태를 보고 있을 때 굉장히 유용하다.
데이터를 관리하는 로직을 컴포넌트에서 빼면, 컴포넌트는 정말 뷰만 관리할 수 있기 때문에 코드가 깔끔해져 유지보수에도 유리하다.
2️⃣ 상태관리 흐름
▶️ 리덕스 store를 Component에 연결한다.
▶️ Component에서 상태 변화가 필요할 때 Action을 부른다.
▶️ Reducer를 통해서 새로운 상태 값을 만들고
▶️ 새 상태값을 Store에 저장한다.
▶️ Component는 새로운 상태값을 받아온다(props를 통해 받아오니까 다시 렌더링 된다).
✅ 리덕스 살펴보기
1️⃣ 리덕스 개념과 용어
리덕스는 데이터를 한 군데 몰아넣고 여기저기에서 꺼내볼 수 있게 하는 것
👌 State
리덕스에서는 저장하고 있는 상태값("데이터"라고 생각해도 된다)를 state라고 부른다.
딕셔너리 형태 ({[key] : value}) 로 보관한다.
👌 Action
상태에 변화가 필요할 때(가지고 있는 데이터를 변경할 때) 발생하는 것
// 액션은 객체. 이런 식으로 쓰인다. type은 이름같은 거! 정하는 임의의 문자열을 넣는다. {type: 'CHANGE_STATE', data: {...}} |
👌 ActionCreator
액션 생성 함수라고도 부른다. 액션을 만들기 위해 사용한다.
//이름 그대로 함수 const changeState = (new_data) => { // 액션을 리턴한다! (액션 생성 함수니까) return { type: 'CHANGE_STATE', data: new_data } } |
👌 Reducer
리덕스에 저장된 상태(=데이터)를 변경하는 함수
액션 생성 함수를 부르고 -> 액션을 만들면 -> 리듀서가 현재 상태(=데이터)와 액션 객체를 받아서 -> 새로운 데이터를 만들고 -> 리턴해준다.
// 기본 상태값을 임의로 정해주었다. const initialState = { name: 'mean0' } function reducer(state = initialState, action) { switch(action.type){ // action의 타입마다 케이스문을 걸어주면, // 액션에 따라서 새로운 값을 돌려줍니다! case CHANGE_STATE: return {name: 'mean1'}; default: return false; } } |
👌 Store
프로젝트에 리덕스를 적용하기 위해 만드는 것
스토어에는 리듀서, 현재 애플리케이션 상태, 리덕스에서 값을 가져오고 액션을 호출하기 위한 몇 가지 내장 함수가 포함되어 있다. 생김새는 딕셔너리 혹은 json 처럼 생겼다.
내장함수는 공식문서에서 확인 가능
👌 dispatch
스토어의 내장 함수. 액션을 발생 시키는 역할을 한다.
// 실제로는 이것보다 코드가 길지만, // 간단히 표현하자면 이런 식으로 우리가 발생시키고자 하는 액션을 파라미터로 넘겨서 사용한다. dispatch(action); |
2️⃣ 리덕스의 3가지 특징
👌 store는 1개만 쓴다.
리덕스는 단일 스토어 규칙을 다른다. 한 프로젝트에 스토어는 한 개만 쓴다.
👌 store의 state(데이터)는 오직 action으로만 변경할 수 있다.
리액트에서 state는 setState()나, useState() 훅을 써서만 변경 가능했다. 데이터가 마구잡이로 변하지 않도록 불변성을 유지해주기 위함이다.
리덕스에 저장된 데이터 = 상태 = state는 읽기 전용이다.
기존에 있던 값을 수정하지 않고 새로운 값을 만들어서 상태를 갈아끼운다.
ex) A에 +1을 할 때, A=A+1이 되는 것이 아니고 A'=A+1 이라고 새로운 값을 만들고 A를 A'로 바꾼다.
👌 어떤 요청이 와도 리듀서는 같은 동작을 해야 한다.
🔹 리듀서는 순수한 함수여야 한다.
순수한 함수란,
- 파라미터 외의 값에 의존하지 않아야 하고
- 이전 상태는 수정하지(건드리지) 않는다. 변화를 준 새로운 객체를 return 해야 한다.
- 파라미터가 같으면 항상 같은 값을 반환한다.
- 리듀서는 이전 상태와 액션을 파라미터로 받는다.
✅ 리덕스 써보기
1️⃣ 덕스 구조
- 보통 리덕스를 사용할 때는, 모양새대로 action, actionCreator, reducer를 분리해서 작성한다. 액션은 액션끼리, 액션생성함수는 액션생성함수끼리, 리듀서는 리듀서끼리 작성한다.
- 덕스 구조는 모양새로 묶는 대신 기능으로 묶어 작성한다. 버킷리스트를 예로 들자면, 버킷리스트의 action, actionCreator, reducer를 한 파일에 넣는 것
🔹 덕스 구조 참고 사이트 : https://github.com/erikras/ducks-modular-redux
2️⃣ 첫 번째 모듈 만들기
일단 폴더 만들 때 구조는 src 폴더 아래에 redux라는 폴더, 그 안에 modules라는 폴더, modules 아래에 bucket.js처럼 파일을 만들고 그 안에 리덕스 모듈 예제를 붙여넣으면 된다.
▶️ Action
// 액션 타입을 정해준다. const LOAD = "bucket/LOAD"; const CREATE = "bucket/CREATE"; |
원래 모듈 예제 보면 const UPDATE, REMOVE도 있는데 그건 bucketList에선 사용하지 않으므로 삭제
▶️ initialState
초기 상태값, 즉 기본 값 만들어주기
const initialState = { list: ["영화관 가기", "매일 책읽기", "수영 배우기"], }; |
▶️ Action Creator
액션 생성 함수 작성하기
// 액션을 만들어줄 함수 export const loadBucket = (bucket) => { return { type: LOAD, bucket }; }; export const createBucket = (bucket) => { return { type: CREATE, bucket }; }; |
▶️ Reducer
load할 땐, 가지고 있던 기본값을 그대로 뿌려주면 된다.
create할 땐, 새로 받아온 값을 가지고 있던 값에 더해서 리턴해주면 된다.
// 실질적으로 store에 들어가 있는 데이터를 변경하는 곳 export default function reducer(state = initialState, action = {}) { switch (action.type) { case "bucket/LOAD": return state; case "bucket/CREATE": const new_bucket_list = [...state.list, action.bucket]; return { list: new_bucket_list }; default: return state; } } |
▶️ Store
redux 폴더 하위에 configStore.js 파일 만들고 스토어 만들어보기
//configStore.js import { createStore, combineReducers } from "redux"; import bucket from "./modules/bucket"; // root 리듀서를 만들어준다. // 나중에 리듀서를 여러개 만들게 되면 여기에 하나씩 추가해주는 거 const rootReducer = combineReducers({ bucket }); // 스토어를 만들기 const store = createStore(rootReducer); export default store; |
✅ 리덕스와 컴포넌트 연결하기
1️⃣ Store 연결하기
👌 index.js
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; import {BrowserRouter} from "react-router-dom"; // 버킷리스트에 리덕스를 주입해줄 프로바이더를 불러오기 import { Provider } from "react-redux"; // 연결할 스토어도 가지고 오기 import store from "./redux/configStore"; ReactDOM.render( <Provider store={store}> <BrowserRouter> <App /> </BrowserRouter> </Provider>, document.getElementById("root") ); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals(); |
✅ 컴포넌트에서 리덕스 데이터 사용하기
1️⃣ 컴포넌트에서 리덕스 데이터 사용하는 법
👌 리덕스 훅
상태, 즉 데이터를 가져오는 것 하나, 상태를 업데이트할 수 있는 것 하나
이렇게 두 가지를 가장 많이 사용한다.
더 많은 훅을 보고 싶을 때 공식문서 : https://react-redux.js.org/api/hooks
🔹 useDispatch : 데이터를 업데이트할 때
🔹 useSelector : 데이터를 가져올 때
import {useDispatch, useSelector} from "react-redux"; |
👌BucketList.js 에서 redux 데이터 가져오기
🔹 useSelector((state) => state.bucket)
configStore.js에서 루트 리듀서를 만들었다. state는 리덕스 스토어가 가진 전체 데이터
... // redux 훅 중, useSelector를 가져온다. import { useSelector } from "react-redux"; const BucketList = (props) => { let history = useHistory(); // 이 부분은 주석처리! // console.log(props); // const my_lists = props.list; // 여기에서 state는 리덕스 스토어가 가진 전체 데이터. // 우리는 그 중, bucket 안에 들어있는 list를 가져온다. const my_lists = useSelector((state) => state.bucket.list); return ( <ListStyle> {my_lists.map((list, index) => { return ( <ItemStyle className="list_item" key={index} onClick={() => { history.push("/detail"); }} > {list} </ItemStyle> ); })} </ListStyle> ); }; ... |
👌 App.js에서 redux 데이터 추가하기
🔹 import 부터
// useDispatch를 가져오기 import {useDispatch} from "react-redux"; // 액션생성함수도 가져오기 import { createBucket } from "./redux/modules/bucket"; |
🔹 useDispatch 훅 쓰기
const dispatch = useDispatch(); const addBucketList = () => { // 스프레드 문법! // 원본 배열 list에 새로운 요소를 추가해주었다. // 여긴 이제 주석처리! // setList([...list, text.current.value]); dispatch(createBucket(text.current.value)); }; |
2️⃣ 상세페이지에서 버킷리스트 내용을 띄어보기
👌 몇 번째 상세에 와 있는지 알아야 하므로, URL 파라미터 적용하기
🔹 App.js
<Route exact path="/detail/:index" component={Detail} /> |
🔹 BucketList.js
{my_lists.map((list, index) => { return ( <ItemStyle className="list_item" key={index} onClick={() => { history.push("/detail/"+index); }} > {list} </ItemStyle> ); })} ... |
👌 상세페이지에서 버킷리스트 내용을 띄어보기
🔹 Detail.js
// 리액트 패키지를 불러오기 import React from "react"; // 라우터 훅 불러오기 import {useParams} from "react-router-dom"; // redux hook을 불러오기 import { useSelector } from "react-redux"; const Detail = (props) => { // 스토어에서 상태값 가져오기 const bucket_list = useSelector((state) => state.bucket.list); // url 파라미터에서 인덱스 가져오기 const params = useParams(); const bucket_index = params.index; return <h1>{bucket_list[bucket_index]}</h1>; }; export default Detail; |
'Front-End, CS 스터디 > 항해99 - React 스터디' 카테고리의 다른 글
[리액트 React] 입문 학습 자료 정리 (0) | 2022.07.28 |
---|---|
[리액트 React] 기초반 강의 4주차 정리 (2) | 2022.07.28 |
[리액트 React] 3주차 입문 주차 팀 과제 정리 (0) | 2022.07.24 |
[리액트 React] 기초반 강의 2주차 정리 (0) | 2022.07.24 |
[리액트 React] 기초반 강의 1주차 정리 (0) | 2022.07.22 |