[Redux] react-redux 로 CRUD 구현하기

임홍원·2023년 11월 17일
0

Redux

목록 보기
2/4
post-thumbnail

Redux store 세팅

import { createStore } from "redux";
import { combineReducers } from "redux";
import workoutReducer from "redux/reducers/workout";
import menuReducer from "redux/reducers/menu";

const rootReducer = combineReducers({ workoutReducer, menuReducer });
const store = createStore(rootReducer);

export default store;

우선 필요한 Redux를 세팅해준다.
combineReducers로 리듀서들을 묶어주고, createStore로 store를 생성한다.

Reducer

import dummy from "../../fakedata.json";

//action values
export const ADD = "workout/ADD";
export const DELETE = "workout/DELETE";
export const MODIFY = "workout/MODIFY";

//action creators
export const addItem = (payload) => {
	return {
		type: ADD,
		payload,
	};
};

export const deleteItem = (id) => {
    return {
        type: DELETE,
        payload: id,
    }
}

export const modifyItem = (payload) => {
    return {
        type: MODIFY,
        payload,
    }
}

//inital state
const initialState = dummy;

const workoutReducer = (state = initialState, action) => {
	switch (action.type) {
		case ADD:
			return [...state, action.payload];
        case DELETE:
            return state = state.filter(s => s.id !== action.payload);
        case MODIFY:
            {
                const filteredData = state.filter(s => s.id !== action.payload.id)
                return [...filteredData, action.payload]
            }
		default:
			return state;
	}
};

export default workoutReducer;

CRUD에 필요한 reducer를 작성한다.
action valuesaction creators를 만들어 휴먼에러를 예방한다.
후에 컴포넌트에서 action creatordispatch하여 사용할 것이기 때문에 action creators의 return값은 객체로 설정한다.
우리는 state를 업데이트 할 것이기 때문에 리듀서 함수는 항상 state를 업데이트 하여야 한다.

Component에서 사용하기

// add item
import { useDispatch } from "react-redux";
import { addItem } from "redux/reducers/workout";

const Form = () => {
	const dispatch = useDispatch(); // action을 dispatch하기 위한 useDispatch 선언
	const [nickname, setNickname] = useState("");
	const [content, setContent] = useState("");
	const [workout, setWorkout] = useState("스쿼트");

	const nicknameHandler = (e) => {
		setNickname(e.target.value);
	};

	const contentHandler = (e) => {
		setContent(e.target.value);
	};

	const workoutHandler = (e) => {
		setWorkout(e.target.value);
	};

	const submitHandler = (e) => {
		e.preventDefault();

		const data = {
			createdAt: new Date().toISOString(),
			nickname,
			avatar: "https://static.vecteezy.com/system/resources/previews/009/292/244/original/default-avatar-icon-of-social-media-user-vector.jpg",
			content,
			writedTo: workout,
			id: uuid(),
		};

		if (nickname.trim() === "") {
			alert("Please enter a nickname");
			return;
		}

		if (content.trim() === "") {
			alert("Please enter a content");
			return;
		}

		dispatch(addItem(data)); // reducer로 action dispatch
        
		setNickname("");
		setContent("");
	}; // 편의상 코드 생략
// delete item & modify item
import { useDispatch, useSelector } from 'react-redux';
import { deleteItem, modifyItem } from 'redux/reducers/workout';

const FanLetter = () => {
    const dispatch = useDispatch(); // action을 dispatch하기 위한 useDispatch 선언
    const workoutData = useSelector(state => state.workoutReducer); // useSelector로 현재 state 가져오기
	const { id } = useParams();
	const filteredData = workoutData.filter((w) => w.id === id)[0];
	const [isModifyBtnClicked, setIsModifyBtnClicked] = useState(false);
	const [modifyText, setModifyText] = useState(filteredData.content);

	const data = {
		createdAt: filteredData.createdAt,
		nickname: filteredData.nickname,
		avatar: filteredData.avatar,
		content: modifyText,
		writedTo: filteredData.writedTo,
		id: filteredData.id,
	};

	const navigate = useNavigate();

	const navigateHandler = () => {
		navigate("/");
	};

	const deleteWorkoutHandler = (id) => {
		if (window.confirm("삭제하시겠습니까?")) {
            dispatch(deleteItem(id));
			navigateHandler();
		}
	};

	const modifyHandler = () => {
		setIsModifyBtnClicked(!isModifyBtnClicked);
	};

	const textModifyHandler = (e) => {
		setModifyText(e.target.value);
	};

	const textModifyConfirmHandler = (e) => {
		if (window.confirm("수정하시겠습니까?")) {
			if (modifyText.trim() === "") {
				alert("내용을 채워주세요");
				return;
			}
			if (filteredData.content === modifyText) {
				alert("변경된 내용이 없습니다.");
				return;
			}

            dispatch(modifyItem(data)); // action dispatch
			setIsModifyBtnClicked(!isModifyBtnClicked);
			navigateHandler();
		}
	}; // 편의상 코드 생략

이제 우리는 useDispatch를 통해 action을 리듀서 함수(store)로 보낼 수 있다.
또한 useSelector로 리듀서의 현재 state를 불러올 수 있다.

0개의 댓글