버튼 컴포넌트 내부의 기능을 구현하기 이전에 등록 페이지에서 컴포넌트들을 나누었기 때문에 전역 상태 관리가 필요하였다.
구체적으로 설명하자면
MBTI를 선택하는 부분에서의 MBTI 상태관리
컬러를 선택하는 부분에서의 컬러 상태관리
이렇게 두 개가 필요하였다.
따라서 Zustand를 설치하였고
import { create } from 'zustand';
import { MbtiOptions } from '../types/mbtiOptions';
interface SelectedMbtiState {
selectedMbti: MbtiOptions;
setSelectedMbti: (mbti: MbtiOptions) => void;
}
// devtools를 사용하는 경우, 타입을 지정해줘야 합니다.
const useSelectedMbtiStore = create<SelectedMbtiState>((set) => ({
selectedMbti: {
EI: null,
SN: null,
TF: null,
JP: null,
},
setSelectedMbti: (mbti: MbtiOptions) => set({ selectedMbti: mbti }),
}));
export default useSelectedMbtiStore;
import { create } from 'zustand';
interface SelectedColorState {
selectedColor: string;
setSelectedColor: (color: string) => void;
}
// devtools를 사용하는 경우, 타입을 지정해줘야 합니다.
const useSelectedColorStore = create<SelectedColorState>((set) => ({
selectedColor: '#ffffff',
setSelectedColor: (color: string) => set({ selectedColor: color }),
}));
export default useSelectedColorStore;
이렇게 두 개의 store를 만들었고
import { useState, useEffect } from 'react';
import { MbtiOptions } from '../types/mbtiOptions';
import mbtiCategories from '../constant/mbtiCategories';
import useSelectedMbtiStore from '../store/selectedMbtiStore';
const MbtiSelectContent = () => {
const { setSelectedMbti } = useSelectedMbtiStore();
const [selectedOptions, setSelectedOptions] = useState<MbtiOptions>({
EI: null,
SN: null,
TF: null,
JP: null,
});
// 버튼 클릭 시 상태 업데이트
const handleSelect = (category: string, type: string) => {
setSelectedOptions((prev) => ({
...prev,
[category]: type, // 선택된 항목만 활성화
}));
};
useEffect(() => {
setSelectedMbti(selectedOptions);
}, [selectedOptions, setSelectedMbti]);
...
};
export default MbtiSelectContent;
버튼 클릭으로 로컬 상태가 변화될 때마다 전역 상태를 갱신시켜주는 방식으로 구현하였다.
import React, { useState, useEffect } from 'react';
import { HexColorPicker } from 'react-colorful';
import useSelectedColorStore from '../../store/selectedColorStore';
interface SelectColorModalProps {
closeModal: () => void;
}
const SelectColorModal = ({ closeModal }: SelectColorModalProps) => {
const { setSelectedColor } = useSelectedColorStore();
const [color, setColor] = useState<string>('#ffffff');
useEffect(() => {
// color 상태가 변경될 때 Zustand 스토어에 업데이트
setSelectedColor(color);
}, [color, setSelectedColor]);
...
};
export default SelectColorModal;
위 컴포넌트도 마찬가지로 로컬 변수가 변경될 때마다 전역 상태를 갱신하도록 하였다.
이제 버튼 내부의 기능을 구현하여야 했다.
등록 로직을 생각해야하는데 먼저 전역 상태에 대한 유효성 검사 로직을 구현하고
post요청으로 등록을 하도록 구현해줘야한다.
api통신 부분은 일단 제외하고 유효성 검사 유틸함수를 구현하였다.
import { MbtiOptions } from '../types/mbtiOptions';
const checkMbti = (mbti: MbtiOptions) => {
if (mbti.EI && mbti.JP && mbti.SN && mbti.TF) {
return true;
}
return false;
};
export default checkMbti;
mbti 모든 카테고리의 데이터가 있을 때 true 값을 리턴하도록 해주었으며
컬러는 초기값이 #ffffff 흰색이라 데이터 유효성이 필요가 없었다.
import { toast } from 'react-toastify';
import useSelectedColorStore from '../store/selectedColorStore';
import useSelectedMbtiStore from '../store/selectedMbtiStore';
import checkMbti from '../util/checkMbti';
const AssignColorButton = () => {
const { selectedColor } = useSelectedColorStore();
const { selectedMbti } = useSelectedMbtiStore();
const handleAssignColor = () => {
if (checkMbti(selectedMbti)) {
console.log(selectedColor);
} else {
toast.error('mbti 항목을 모두 선택해주세요');
}
};
return (
<button
onClick={handleAssignColor}
type="button"
className="flex px-[22px] py-[22px] justify-center items-center rounded-[16px] bg-[#464E5E] text-[24px] font-bold text-white"
>
컬러 등록
</button>
);
};
export default AssignColorButton;
버튼 컴포넌트에서 버튼을 클릭했을 때 다음과 같이 유틸 함수가 실행되도록 해주었다.