Develop record

[React] Redux state 변경 본문

Frontend/React

[React] Redux state 변경

seong's log 2024. 3. 29. 01:46

state 변경

1. store.js 에서 state 변경 함수 만들기

2. export

let user = createSlice({
  name : 'user',
  initialState : 'kim',
  reducers : { // state 수정함수 만들기
    함수명1(state){ // state : 기존 state
      return '변경값' // 변경 state
    },
    함수명2(){
      return 
    }
  }
})

let user = createSlice({
  name : 'user',
  initialState : 'kim',
  reducers : { 
    changeName(state){ 
      return 'john'
    }  
  }
})

// state 변경 함수 export 해서 다른 곳에서 사용하기 좋도록
export let {export 하고 싶은 함수명 : 함수명1, 함수명2 ...} = user.actions 
// user.actions  : state 변경 함수들이 그 자리에 출력 됨

export let {changeName} = user.actions

 

3. state 변경 함수 사용

4. import

5. useDispatch() 변수에 담아 사용

6. dispatch(state변경함수())

import { useDispatch, useSelector } from "react-redux";
import { changeName } from "../store"; 
//store.js 의 state 변경 함수 import

function Cart(){
	let dispatch = useDispatch() 
    // useDispatch() : store.js 에 요청보내주는 함수 -> 변수에 담아 사용
	return(
    	 <button onClick={()=>{
            dispatch(changeName()) 
            //dispatch(state변경함수())로 사용
            //함수를 실행하는 것이 아님 -> changeName() 실행해달라고 store.js에 요청
         }}>+</button>
    )
}

 

state : array / object 경우 변경

1. state.name = ''

2. return { name : '' }

3. 용도가 비슷한 함수 : parameter 빼서  parameter명.payload 해서 사용

4. 코드가 너무 길 경우 파일 따로 빼서 사용하기 (createSlice.js)

import { createSlice } from "@reduxjs/toolkit"

let user = createSlice({
    name : 'user',
    initialState : {name : 'kim', age : 20}, //문자 하나만 필요해도 object로 만드는 것이 수정에 용이
    reducers : { 
      changeName(state){ 
        state.name = 'park' //직접 수정해도 변경 됨
         //return {name : 'park', age : 20}
      },
      // parameter 넣기 action : state 변경함수 -> action으로 parameter 이름을 많이 사용
      changeAge(state, action){ 
        state.age += action.payload
      }
    }
  })
  
  //changeAge(10) // cart.js에서 함수 사용시 ()안의 값이 a.payload에 대입 됨
  //changeAge(100)
  
  export let {changeName, changeAge} = user.actions

  export default user; 
  // export -> store.js 에서 import 해서 사용

 

store.js

import user from './store/userSlice'

export default configureStore({
  reducer: { 
    cart : cart.reducer,
    user : user.reducer
  }
})

 

cart.js

import { changeName,changeAge } from "../store/userSlice";

function Cart(){

    let cart = useSelector((state)=>{return state})
    let dispatch = useDispatch()
    
    return(
        <h6>{cart.user.name} {cart.user.age}의 장바구니</h6>
        <button onClick={()=>{dispatch(changeAge(100))}}>버튼</button>
        // changeAge() 안에 값이 action.payload 에 대입 -> 누를 때마다 +100 증가
    )
}

 

1. 변경하기 버튼 클릭 시 각각의 수량 +1 씩 증가

2. detail/번호 url 에서 주문하기 버튼 클릭시 장바구니에 상품추가하기

 

store.js

import { act } from 'react-dom/test-utils';
import user from './store/userSlice'
import { configureStore, createSlice } from '@reduxjs/toolkit'

let cart = createSlice({
    name : 'cart',
    initialState : [
        {id : 0, name : 'White and Black', count : 2},
        {id : 2, name : 'Grey Yordan', count : 1}],
    reducers: {
        changeCount(state,action){
            state[action.payload].count +=1; 
            
            // 조건에 맞는 index 값 찾기
            // a : state 값
            // let index = state.findIndex((a)=>{ return a.id ===  action.payload })
            // a.id ===  action.payload : id 가 같을 때 count +
            // state[index].count++
           
       },
       addCart(state,action){
            let add = {
                id : action.payload.id, 
                name : action.payload.title,
                count : 1
            }
            console.log("action.payload")
            console.log(add)
            state.push(add)
       },
        delCart(state, action){
            let index = state.findIndex((a)=>{return a.id === action.payload.id })
            state.splice(index,1)
            //delete state[index]
       }
    }
})

export let {changeCount, addCart} = cart.actions

export default configureStore({
  reducer: { 
    cart : cart.reducer,
    user : user.reducer
  }
})

 

cart.js

import { Table } from "react-bootstrap";
import { useDispatch, useSelector } from "react-redux";
import { changeName,changeAge } from "../store/userSlice";
import {changeCount} from "../store";


function Cart(){

    let cart = useSelector((state)=>{return state.cart})
    let user = useSelector((state)=>{return state.user})
    let dispatch = useDispatch()
    
    return(     
        <div>
            <h6>{user.name} {user.age}의 장바구니</h6>
            <button onClick={()=>{dispatch(changeAge(100))}}>버튼</button>
           
            <Table>
                <thead>
                    <tr>
                        <th>id</th>
                        <th>상품명</th>
                        <th>수량</th>
                        <th>변경하기</th>
                    </tr>
                </thead>
                <tbody>
                    
                        {
                            cart.map(function(a,i){
                                return(
                                    <tr key={i}>
                                    <td>{a.id}</td>
                                    <td>{a.name}</td>
                                    <td>{a.count}</td>
                                    <td>안녕</td>
                                    <td>
                                        <button onClick={()=>{                  
                                            dispatch(changeCount(i))                                            
                                        }}>+</button>
                                    </td>
                                    <td>
                                        <button onClick={()=>{                  
                                            dispatch(delCart(a))                                            
                                        }}>삭제</button>
                                    </td>
                                    </tr> 
                                )
                               
                            })
                        }                   
            </tbody>
        </Table> 
      </div>
    )
}

export default Cart;

 

detail.js

import { useEffect, useState } from "react";
import { Container, Row, Col } from "react-bootstrap";
import { useDispatch, useSelector } from "react-redux";
import { useParams } from "react-router";
import styled from "styled-components";
import { addCart } from "../store";


function Detail(props){

    let [count, setCount] = useState(0)
    let [input, setInput] = useState("")
    let [alert, setAlert] = useState(false)
    let cart = useSelector((state)=>state.cart)
    let dispatch = useDispatch()

    console.log(cart);
    useEffect(()=>{
        var numberChk = /^[0-9]*$/;
        if(!input.match(numberChk)){
            setAlert(true)
        }else{
            setAlert(false)
        }  
    },[input]) 

    let{id} = useParams();
    if(id >= props.shoes.length){
        return <div>없는상품입니다.</div>
    }

    return(
        <div>
            <Container>
                <button onClick={()=>{ setCount (count+1)}}>버튼{count}</button>
                <Row>
                    <Col md={6}>
                        <img src={"https://codingapple1.github.io/shop/shoes"+(props.shoes[id].id+1)+".jpg"} width="80%"/>
                        <h4>{props.shoes[id].title}</h4>
                        <p>{props.shoes[id].content}</p>
                        <p>{props.shoes[id].price}원</p>
                        <button className="btn btn-danger" onClick={()=>{
                            dispatch(addCart(props.shoes[id]))
                        }}>주문하기</button>
                    </Col>                                       
                </Row>
                <input type="text" onChange={(e)=>{setInput(e.target.value)}}></input>
                { alert && <div>숫자만 입력가능합니다</div>}
            </Container>
        </div>
    )
   
}

export default Detail;

'Frontend > React' 카테고리의 다른 글

[React] memo  (0) 2024.03.31
[React] react - query , lazy, suspend  (0) 2024.03.31
[React] Redux 셋팅 / state 만들기  (0) 2024.03.26
[React] Context API  (0) 2024.03.26
[React] 애니메이션-transition  (0) 2024.03.25