실습환경: 코드샌드박스 https://codesandbox.io/s/react-new
- 우선 리덕스 라이브러리를 설치한다.(아래 설치 명령 또는 마우스 클릭으로 설치)
- npm i redux react-redux (코드샌드박스에서는 마우스 선택으로 설치 가능하다.아래)
### 리덕스로 상태관리를 사용하는 이유 2가지
####사용하는 이유 1). props(컴포넌트속성-전달객체) 를 state변수로 가져다 사용한다. 장점은 props 속성을 관리하기 편리하다.
- 지난번에 작업했던 리액트js기본의 샌드박스의 소스를 가지고 실습한다. https://kimilguk.tistory.com/839
============================================================
- index.js 수정한 createStore로 리듀서-reducer함수를 사용하여 props대신 state 전역변수로 사용한 소스(아래 //리덕스...)
============================================================
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
import { Provider } from "react-redux"; //리덕스 라이브러리 사용 추가
import { createStore } from "redux"; //리덕스 라이브러리 사용 추가
const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
//리덕스 용 변수와 함수 추가
const param = "프로퍼티스 값"; // props 객체사용을 대신할 param 변수 지정
function reducer(state = param, action) { // action 변수는 다음 TodoList앱에서 사용해 본다.
return state;
}
// createStore함수로 저장소를 만든다.
let store = createStore(reducer);
// App 컴포넌트의 param 속성을 재거하고, Provider 로 감싸준다.(아래)
root.render(
<StrictMode>
<Provider store={store}>
<App />
</Provider>
</StrictMode>
);
============================================================
- App.js 수정한 useSelector로 state 전역변수 사용 소스(아래 //리덕스...)
============================================================
import React, { useState } from "react";
import "./styles.css";
import { useSelector } from "react-redux"; //리덕스 라이브러리 사용 추가
function App(props) {
// props 대신에 리덕스의 state 값을 사용
const param = useSelector((state) => state);
// export 가 여기에 사용되기도 한다.
let count = 0;
const [cnt, setCnt] = useState(0); // [상태변수, 상태함수]
const increase = () => {
count = count + 1;
setCnt(cnt + 1); // 상태함수 실행 시 화면 재생
console.log(count, cnt);
}; // increase함수 종료 후 cnt 변수 값 변경 된다.
return (
<main>
<div>{param}</div>
<div>{count}</div>
<div>state : {cnt}</div>
<button onClick={increase}>증가</button>
</main>
);
}
export default App;
####리덕스를 사용하는 이유2) state(컴포넌트 상태변수) 사용을 간편히 하는 기능이 있다.
- 기술참조 : https://wonit.tistory.com/514
- 컴포넌트의 state 상태변수와 처리액션까지 저장소에 포함 시킨다. : 장점은 처리 액션을 1곳에서 관리 할 수 있다.
- 지난번에 실습한 리액트의 state상태와 화면 다시 렌더링 https://kimilguk.tistory.com/840 (아래)
- Todo List 앱에서 컴포넌트의 state 객체사용을 리덕스로 구현해보기-state가 전역변수처럼 사용된다.
============================================================
- App.js 수정한 dispatch로 store.js의 리듀서 함수를 호출하는 소스(아래 //리덕스...)
============================================================
import React, { useState, useEffect, useRef } from "react";
import "./App.css";
import "./components/TodoList";
import TodoList from "./components/TodoList";
import { useDispatch } from "react-redux"; //리덕스 라이브러리 사용 추가
/**
# 컴포넌트 구조를 만들고, 기능을 정의한다.
1. input 박스로 입력 시키는 화면을 만든다 반복되는 아이템 목록 리스트 부분은 컴포넌트로 분리한다.
2. 위 화면에서 값을 입력하고 할일추가 버튼을 누르면 아이템이 추가된다
3. 아이템 할일삭제 버튼을 누르면 삭제 된다
*/
function App(props) {
// const [todoList, setTodoList] = useState([]);// useState의 set함수대신에 리덕스의 dispatch함수를 사용
const dispatch = useDispatch();
const [todo, setTodo] = useState("");
const inputRef = useRef(); // 화면이 다시 렌더링 되는 것을 방지
const addItem = () => {
setTodo(inputRef.current.value);
//console.log("입력한 값", todo);
//setTodoList([...todoList, todo]); // onChange사용시 기존 배열에 할일 추가
//setTodoList([...todoList, inputRef.current.value]); // 화면이 다시 렌더링 되는 것을 방지-todo 대신사용
if (inputRef.current.value) {
dispatch({ type: "addItem", todo: inputRef.current.value }); // 디스패쳐로 스토어의 리듀서함수를 호출할 수 있다.
}
};
useEffect(() => {
// 상태함수:화면이 마운트-로딩된 이후에 todo값이 변경되면 자동으로 실행된다.
console.log("입력한 값", todo);
setTodo(""); // 입력한 값을 초기화 한다.
inputRef.current.value = ""; // 입력 화면을 초기화 한다.
}, [todo]);
return (
<main>
<h1>할일목록-Todo List</h1>
<input type="text" ref={inputRef} />
{/*value={todo} onChange={(e) => setTodo(e.target.value)}*/}
{/* console.log(e.target.value) */}
<button onClick={addItem}>할일추가</button>
<TodoList />
</main>
);
}
export default App;
============================================================
- store.js 신규파일 추가한 후 state 초기화 및 리듀서 함수에서 action타입으로 state값 변경하는 소스(아래)
- 보통 아래 처럼 3개파일로 나누지만, 우리는 수업에서 사용하기 때문에 store.js 파일 1개에 모두 적용한다.
네이밍 참고1- actions.js(action 생성을 하고 해당 action이 어떤 일을 수행할지 지정한다.)
네이밍 참고2- reducer.js(action 을 실행시킬 reducer-action 객체를 받아 state 를 변경시킨다.)
네이밍 참고3- store.js(createStore함수로 스토어객체를 생성한다.)
============================================================
import { createStore } from "redux"; //리덕스 라이브러리 사용 추가
const initialState = {
//리덕스 용 상태 초기값 선언
todoList: []
};
const reducer = (state = initialState, action) => {
console.log(action.type, "여기", action.todo);
if (action.type === "addItem") {
return {
// 만약 다른 state 가 존재한다면 전개 연산 ...state 를 해야함
// 하지만 현재 state 에는 todoList 하나 뿐이라 todoList 만 반환하면 됨
todoList: [...state.todoList, action.todo]
};
} else {
return state;
}
};
// createStore함수로 저장소를 만든다.
let store = createStore(reducer);
export default store;
============================================================
- index.js 수정한 리액트리덕스의 Provider로 감싸주면서 임포트한 store.js을 속성으로 추가하는 소스(아래 //리덕스...)
============================================================
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
import { Provider } from "react-redux"; //리덕스 라이브러리 사용 추가
import store from "./store";
const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
// App 컴포넌트의 param 속성을 재거하고, Provider 로 감싸준다.(아래)
root.render(
<StrictMode>
<Provider store={store}>
<App />
</Provider>
</StrictMode>
);
============================================================
- TodoList.jsx 수정한 useSelector로 state 전역변수이 todoList를 사용한 소스(아래 //리덕스...)
============================================================
import React from "react";
import TodoItem from "./TodoItem";
import { useSelector } from "react-redux";
function TodoList(props) {
const todoList = useSelector((state) => state.todoList);
console.log("할일 목록: ", todoList);
return (
<div>
<h2>목록</h2>
{todoList.map((
item,
index //map함수의 자식컴포넌트에 key 속성이 필요하다.
) => (
<TodoItem item={item} key={index} />
))}
{/*<TodoItem />
<TodoItem />*/}
</div>
);
}
export default TodoList;
- 리덕스 전역변수 상태관리를 사용한 결과(아래)
TypeScript-타입스크립트의 특징 (1) | 2023.10.03 |
---|---|
리액트-리덕스 향상된 버전인 리덕스js 툴킷 사용 예 (0) | 2023.10.01 |
리액트의 state상태와 화면 다시 렌더링(re rendering) (0) | 2023.09.27 |
리액트js 기본 (0) | 2023.09.26 |
JS(ES5) vs EcmaScript6(ES6) 기본 (0) | 2023.09.22 |
댓글 영역