상세 컨텐츠

본문 제목

리액트에서 상태-state를 전역변수처럼 사용하는 리덕스 실습

노드js·자바스크립트

by 김일국 2023. 9. 28. 19:05

본문

실습환경: 코드샌드박스 https://codesandbox.io/s/react-new 

- 우선 리덕스 라이브러리를 설치한다.(아래 설치 명령 또는 마우스 클릭으로 설치)

- npm i redux react-redux (코드샌드박스에서는 마우스 선택으로 설치 가능하다.아래)

위 샌드박스 화면에서 Dependencies 의 검색창을 사용하면 쉽게 설치 할 수 있다.(위)

### 리덕스로 상태관리를 사용하는 이유 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;

- 리덕스 전역변수 상태관리를 사용한 결과(아래)

관련글 더보기

댓글 영역