본문 바로가기
> 메모/React

[리액트] Redux 사용 ( 파일 분할 / addCount / findIndex )

by 자몽주스 2024. 6. 10.
728x90
반응형
파일분할
let user = createSlice({
  name: "user",
  initialState: { name: "kim", age: 20 },
  reducers: {
    changeName(state) {
      state.name = "park";
    },
    increase(state, action) {
      state.age += action.payload;
    },
  },
});

store.js 에 있는

해당코드가 넘 길어서 따로 파일로 빼고싶을 때

1. 따로 store 폴더 만든 다음 userSlice.js 파일 생성하고 import와 export
import { createSlice } from "@reduxjs/toolkit";

let user = createSlice({
  name: "user",
  initialState: { name: "kim", age: 20 },
  reducers: {
    changeName(state) {
      state.name = "park";
    },
    increase(state, action) {
      state.age += action.payload;
    },
  },
});

export default user;

다른 파일 생성해주고 import 해주기.

export 도 해줘야 함

2. store.js 에서는 갖다쓰게 하기 - store.js 에 import
import user from "./store/userSlice";
3. userSlice 파일 changeName, increase 함수 userSlice에 옮겨주기
export let { changeName, increase } = user.actions;

export 한 changeName 함수, increase 함수 옮겨줌.

import { createSlice } from "@reduxjs/toolkit";

let user = createSlice({
  name: "user",
  initialState: { name: "kim", age: 20 },
  reducers: {
    changeName(state) {
      state.name = "park";
    },
    increase(state, action) {
      state.age += action.payload;
    },
  },
});
export let { changeName, increase } = user.actions;

export default user;
4. 경로 수정 - Cart.js 가 사용하고 있어서 경로 수정 해주기.
import { changeName, increase } from "./../store/userSlice.js";

+ 버튼을 누르면

옆에 있는 수량이 +1 되는 기능
수정함수 = addCount

let cart = createSlice({
  name: "cart",
  initialState: [
    { id: 0, name: "White and Black", count: 2 },
    { id: 2, name: "Grey Yordan", count: 1 },
  ],
});
1. + 버튼을 누르면 수량(count)state 를 수정
store 안에 있는 state 를 수정하고 싶으면 reducers에다가 state 수정함수 만들기
state 변경 함수 addCount() 사용
increase() 랑 차이 >>
함수 이름 자체에는 특별한 차이가 없으며, increase()와 addCount() 는 동일한 기능을 할 수 있다.

increase():
일반적으로 어떤 값이나 수치를 증가시킬 때 사용할 수 있는 이름.
예: 사용자 나이(age) 증가, 상품 수량 증가 등.

addCount():
좀 더 구체적으로 수량(count)을 증가시킬 때 사용할 수 있는 이름.
예: 쇼핑 카트에서 특정 상품의 수량 증가 등.

상품 수량을 증가시키고 싶다면 addCount()가 더 명확할 수 있다.
나이 증가 같은 일반적인 증가를 다룰 때는 increase()가 더 적합하다.

파라미터 state 추가해주면

위에 있는 배열 다 출력된다.

2. addCount 사용
0번째 항목에 count를 ++해주세요. 라고 코드 짜기
  reducers: {
    addCount(state) {
      state[0].count++;
    },
  },
3. addCount 사용
파라미터(action) 만들어서 활용해주기
파라미터 + payload  써주기
  reducers: {
    addCount(state, action) {
      state[action.payload].count++;
    },
  },

2번 째 파라미터 action 써주기.

addCount ()  소괄호 안에 숫자 넣어서 원하는 인덱스 수정 가능해짐.

소괄호 안의 숫자 데이터가 payload 자리에 도착.

4. export 도 해주기
export let { addCount } = cart.actions;
5. 사용하려는 곳에 import 하기
import {addCount} from "./../store"
6. 버튼에 dispatch 사용해서 addCount 실행해주기
            <button
                    onClick={() => {
                      dispatch(addCount(0));
                    }}
                  >
                    +
                  </button>

버튼 0만 수량 +1이 되는 것 확인.

7. addCount(i) 로 수정하기

i 를 집어넣으면 

반복문이 돌 때마다

인덱스 마냥 0,1,2 이렇게 돎


정렬 버튼 있을 시
인덱스 별로 +1 이 아닌
id 를 찾아서 수량 +1 을 해 줘야할 경우
( 버튼을 누르면 옆에 있는 id 를 갖고오게끔 )
- findIndex() 사용
왜 id 를 찾아야 하는걸까? 인덱스를 사용하면 안될까? >>>
배열을 정렬하게 되면 인덱스가 변경되기 때문
정렬 후에도 특정 항목의 count를 정확하게 증가시키려면 고유한 id 를 사용해야 함
인덱스를 사용하면, 정렬 후에 엉뚱한 항목의 count가 증가할 수 있다.

id를 기준으로 count를 증가시키면 배열이 정렬되거나
항목의 순서가 변경되어도 정확하게 원하는 항목의 count를 증가시킬 수 있다.
let cart = createSlice({
  name: "cart",
  initialState: [
    { id: 0, name: "White and Black", count: 2 },
    { id: 2, name: "Grey Yordan", count: 1 },
  ],
  reducers: {
    addCount(state, action) {
      state[action.payload].count++;
    },
  },
});

cart state 살펴보면 id 확인 가능

		<button
                    onClick={() => {
                      dispatch(addCount(state.cart[i].id));
                    }}
                  >
                    +
                  </button>

id 를 뽑아옴 

state.cart[i].id는 버튼과 연결된 상품의 id를 의미

버튼누르면 이렇게 옆에 있던 상품 id를 payload로 전송

1. id 를 state 변경함수로 전송

state 변경함수는 id 전부를 갖고 온다음,

payload 와 똑같은 id 를 가진 상품을 몇 번째 있는 지 찾기.

( id를 기준으로 배열 내에서 해당 항목을 찾은 다음 그 항목의 count를 증가 )

 

몇 번째 있는 지를 찾은 다음에 

그 번호를 대괄호 안에다가 입력

id 를 state 변경함수(addCount)로 전송하는 이유? >>>
id를 사용하는 이유는 배열의 순서가 바뀌더라도 특정 항목을 정확하게 찾아내기 위해서

State 변경 함수란?
상태(state)를 변경하는 함수를 의미
reducers객체 내부에 정의된 개별 함수들을 의미
2. findIndex 함수 사용
콜백함수와 return 채워 놓고 시작
let cart = createSlice({
  name: "cart",
  initialState: [
    { id: 0, name: "White and Black", count: 2 },
    { id: 2, name: "Grey Yordan", count: 1 },
  ],
  reducers: {
    addCount(state, action) {
      state.findIndex(() => {});
      state[action.payload].count++;
    },
  },
});

array 자료에서 내가 원하는 항목만 딱 찾고싶은 경우,

findIndex 라는 기본 함수 사용

findIndex 의 역할 =  array에서 원하는 거 몇 번째 있는 지 찾아주는 함수.

state.findIndex((a) => {return 조건식});

사용법 : 파라미터 조건식 입력 가능

a 파라미터는 array 안에 있던 하나하나의 데이터

조건식을 사용해서 어떤 항목을 찾을 지 조건식 형태로 입력하기.

 

return 오른쪽에 쓴 a = a 파라미터

a = array  자료 안에 있던 하나하나의 데이터

a 파라미터랑 action 이랑 무슨 차이 일까? >>
addCount(state, action) {
      let 번호 = state.findIndex((a) => {
        return a.id === action.payload;
      });
      state[번호].count++;
    }​

findIndex의 a 파라미터addCount의 action 파라미터는 각각 다른 역할을 한다.

 

  • state는 배열입니다.
  • a 는 배열의 각 요소를 순회할 때의 현재 요소를 나타냅니다.
    여기서 각 요소는 { id: 0, name: "White and Black", count: 2 }와 같은 객체입니다.

addCount의 action 파라미터 >>>

addCount 함수는 리듀서 함수.
두 개의 매개변수를 받는다.

addCount(state, action) {
  // state: 현재 상태
  // action: 액션 객체
}
  • state: 현재 상태입니다.
    이 상태는 createSlice에서 정의된 초기 상태 및 현재 상태를 나타냅니다.
  • action: 액션 객체입니다.이 객체에는 type과 payload 속성이 있습니다.
action 객체의 구조
-type/payload
{
  type: "cart/addCount",
  payload: 2 // 이 값은 특정 항목의 id입니다.
}


findIndex의 a 파라미터 >>>

배열 메서드로, 배열의 각 요소를 순회하며
특정 조건을 만족하는 첫 번째 요소의 인덱스를 반환
findIndex는 콜백 함수로 각 요소를 전달


a: 배열의 각 요소를 나타냅니다.
state 배열의 각 객체를 의미합니다.
콜백 함수: a를 인수로 받아 조건을 평가합니다.

두 파라미터의 차이 >>
  • action: 리듀서 함수 addCount에 전달되는 액션 객체입니다.
    이 객체는 액션 타입(type)과 추가 데이터(payload)를 포함합니다.
    여기서 payload는 특정 항목의 id입니다.
  • a: findIndex 메서드의 콜백 함수에 전달되는 배열의 각 요소입니다.
    state 배열의 각 객체를 의미합니다.

전체적인 흐름

  1. dispatch 호출: dispatch(addCount(2))가 호출되면 addCount 리듀서 함수가 실행됩니다.
  2. addCount 함수: 이 함수는 state와 action을 인수로 받습니다. 여기서 action.payload는 2입니다.
  3. findIndex 호출: state.findIndex는 state 배열을 순회하며 각 요소 a의 id가 action.payload와 일치하는지 확인합니다.
  4. 인덱스 찾기: 조건을 만족하는 첫 번째 요소의 인덱스를 반환합니다.
  5. count 증가: 해당 인덱스를 사용하여 count를 증가시킵니다.

요약

  • action: addCount 리듀서 함수에 전달되는 액션 객체로, 어떤 상태 변경을 할지에 대한 정보를 담고 있습니다.
    dispatch 와 연결된 상태

  • a: findIndex 메서드의 콜백 함수에 전달되는 현재 배열 요소로, 조건을 평가하기 위해 사용됩니다.
    배열 요소들 forEach 같은 거 할 때 a 파라미터
또 다른 예시 >>

장바구니(cart)에는 여러 상품이 들어 있습니다.

각 상품은 고유한 id를 가지고 있습니다.
let cart = [
  { id: 0, name: "White and Black", count: 2 },
  { id: 2, name: "Grey Yordan", count: 1 },
];​

id가 2인 상품의 수량(count)을 증가시키고 싶습니다.


버튼을 클릭할 때 발생하는 일 >>>

1. 버튼을 클릭합니다
<button
  onClick={() => {
    dispatch(addCount(state.cart[i].id));
  }}
>
  +
</button>​

여기서 state.cart[i].id는 클릭한 버튼과 연결된 상품의 id입니다.
예를 들어, state.cart[i].id가 2라면, 2가 addCount 함수로 전달됩니다.


addCount 함수 분석 >>>
addCount(state, action) {
  // state: 현재 상태 (cart 배열)
  // action: 버튼 클릭 시 전달된 데이터 (여기서는 id)
  
  // action.payload: 클릭한 상품의 id (예를 들어 2)
  let 번호 = state.findIndex((a) => {
    return a.id === action.payload;
  });

  // state[번호].count: 찾은 상품의 count를 증가시킵니다.
  state[번호].count++;
}​

파라미터 설명

  • state: 현재 장바구니(cart)의 상태입니다. 이 예에서는 cart 배열입니다.
  • action: 액션 객체입니다. 여기에는 payload라는 속성이 포함되어 있으며,
    이는 버튼 클릭 시 전달된 데이터(상품의 id)를 담고 있습니다.

findIndex의 a

  • a: findIndex 메서드가 배열의 각 요소를 순회하면서 전달하는 현재 요소입니다.
    여기서는 cart 배열의 각 상품 객체를 의미합니다.
  • 비교: a.id === action.payload
    상품 객체의 id와 클릭한 버튼을 통해 전달된 id(즉, action.payload)를 비교합니다.

간단한 비유 >>
addCount의 action: 버튼을 클릭할 때 전달되는 정보입니다.
예를 들어, "이 버튼을 클릭하면
id가 2인 상품의 수량을 증가시켜주세요!"와 같은 요청입니다.
findIndex의 a: 장바구니(cart) 배열을 하나씩 순회하면서
"이 상품의 id가 2와 같은가요?"를 묻습니다.
맞으면 그 상품의 인덱스를 반환합니다.


동작 과정 요약 >>
버튼 클릭: 특정 상품의 id가 addCount 함수로 전달됩니다.
addCount 함수 실행: action.payload는 클릭한 상품의 id입니다.
findIndex는 cart 배열을 순회하면서
각 상품의 id를 action.payload와 비교합니다.
일치하는 상품을 찾으면, 해당 상품의 count를 증가시킵니다.
return a.id == action.payload;
( 예를들어서 짠 코드 )
      state.findIndex((a) => {
        return a.id == action.payload;
      });

예를 들어서 코드를 짬.

return a.id 부분 분석해보기
    { id: 0, name: "White and Black", count: 2 },
    { id: 2, name: "Grey Yordan", count: 1 },

이 object 배열 데이터들이 a 에 들어감.

object 데이터 안의 id 를 출력해보는 것. (.id 를 뒤에 붙여줌으로서)

그러면 저 자리에 0 이나 2가 하나씩 출력됨.

그거랑 action.payload 랑 비교해보기 ( == action.payload; )

같은게 나왔을 경우,

같은 자료가 몇 번째에 있는지

저 자리에 남겨줌.

action.payload는 버튼 클릭 시 dispatch를 통해 전달된 state.cart[i].id 값
addCount 함수에서 action.payload는 상품의 id를 의미

findIndex를 사용하여 id가 action.payload와 일치하는 상품을 찾아,
해당 상품의 count를 증가시킴
변수(번호) 에 담아줘서 사용
let cart = createSlice({
  name: "cart",
  initialState: [
    { id: 0, name: "White and Black", count: 2 },
    { id: 2, name: "Grey Yordan", count: 1 },
  ],
  reducers: {
    addCount(state, action) {
      let 번호 = state.findIndex((a) => {
        return a.id === action.payload;
      });
      state[번호].count++;
    },
  },
});

변수(번호)를 대괄호에 담으면 끝

a.id == action.payload; 이렇게 둘을 비교하는 이유>>
a.id == action.payload는
배열 내의 각 항목의 id
버튼을 클릭해서 전달된 상품의 id를 비교하여 일치하는 항목을 찾는다

배열의 각 항목 a의 idpayload로 전달된 id를 비교
목적: 특정 id를 가진 항목을 찾기 위해.

 

728x90
반응형