UI 코드와 검색로직 분리(feat. UI/UX 개선)

    어제 토스 slash 2023의 유튜브라이브영상을 보고 버튼을 누르거나 하는 사용자의 행동에 인터렉션을 주는 것이 좋은 UI/UX 라는 것을 보면서 제 포트폴리오 사이트는 이부분이 부족하다는 것을 깨달았습니다.

     

     

    제 포트폴리오 사이트에서 '포트폴리오 보러가기' 버튼을 클릭했을 때 padding을 더 추가해서 버튼이 더 커지도록 코드를 추가했습니다.

     

    결과적으로 버튼을 눌렀을 때 보여지는 반응이 있으니 더 좋았습니다.

     

    또한, 그 과정에서 기존에 작성했던 ProjectPage 컴포넌트의 코드를 보니 UI 코드와 검색관련 코드가 함께 있어서 코드의 가독성이 좋지 않았습니다.

     

    따라서 

    import Projects from "components/Projects";
    import "./index.css";
    import { AiOutlineArrowLeft } from "react-icons/ai";
    import Link from "next/link";
    import data from "data/projects";
    import { useCallback, useReducer } from "react";
    import { AiOutlineSearch } from "react-icons/ai";
    import { Project } from "types/types";
    
    const ProjectPage = () => {
      const reducer = (state: Project[], action: any) => {
        switch (action.type) {
          case "CHANGE_INPUT":
            const filteredData = data.filter(
              (project) =>
                project.title
                  .toLowerCase()
                  .includes(action.payload.toLowerCase()) ||
                project.description
                  .toLowerCase()
                  .includes(action.payload.toLowerCase()) ||
                project.techstack
                  .toLowerCase()
                  .includes(action.payload.toLowerCase())
            );
            return filteredData;
          default:
            return state;
        }
      };
    
      const [state, dispatch] = useReducer(reducer, data);
    
      const onSearch = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
        dispatch({
          type: "CHANGE_INPUT",
          payload: event.target.value,
        });
      }, []);
    
      return (
        <div className="background">
          <div className="page_container">
            <Link href={"/"}>
              <AiOutlineArrowLeft size={20} color={"gray"} />
            </Link>
            <AiOutlineSearch size={17} style={{ marginLeft: "10px" }} />
            <input
              placeholder="Enter your search term"
              onChange={onSearch}
              style={{
                width: "215px",
                padding: "6px",
                border: "1px solid #ccc",
                borderRadius: "5px",
              }}
            />
            <Projects data={state} />
          </div>
        </div>
      );
    };
    
    export default ProjectPage;

    위에 코드에 있는 검색로직인 reducer 함수 등의 코드를 useProjectSearch 라는 이름의 훅으로 분리하고 전체 프로젝트 목록에서 검색한 키워드가 포함된 프로젝트들인 state ,  onSearch라는 함수를 리턴하도록 했습니다. 

     

    import { useReducer, useCallback } from "react";
    import { Project } from "types/types";
    import data from "data/projects";
    
    type Action = {
      type: "CHANGE_INPUT";
      payload: string;
    };
    
    type State = Project[];
    
    const reducer = (state: State, action: Action) => {
      switch (action.type) {
        case "CHANGE_INPUT":
          const filteredData = data.filter(
            (project) =>
              project.title
               .toLowerCase()
               .includes(action.payload.toLowerCase()) ||
              project.description
               .toLowerCase()
               .includes(action.payload.toLowerCase()) ||
              project.techstack
               .toLowerCase()
               .includes(action.payload.toLowerCase())
          );
          return filteredData;
        default:
          return state;
      }
    };
    
    const useProjectSearch = (initialData: Project[]) => {
      const [state, dispatch] = useReducer(reducer, initialData);
    
      const onSearch = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
        dispatch({
          type: "CHANGE_INPUT",
          payload: event.target.value,
        });
      }, []);
    
      return { state, onSearch };
    };
    
    export default useProjectSearch;

     

    import Projects from "components/Projects";
    import "./index.css";
    import { AiOutlineArrowLeft } from "react-icons/ai";
    import Link from "next/link";
    import { AiOutlineSearch } from "react-icons/ai";
    import useProjectSearch from "hooks/useProjectSearch";
    import data from "data/projects";
    
    const ProjectPage = () => {
      const { state, onSearch } = useProjectSearch(data);
    
      return (
        <div className="background">
          <div className="page_container">
            <Link href={"/"}>
              <AiOutlineArrowLeft size={20} color={"gray"} />
            </Link>
            <AiOutlineSearch size={17} style={{ marginLeft: "10px" }} />
            <input
              placeholder="Enter your search term"
              onChange={onSearch}
              style={{
                width: "215px",
                padding: "6px",
                border: "1px solid #ccc",
                borderRadius: "5px",
              }}
            />
            <Projects data={state} />
          </div>
        </div>
      );
    };
    
    export default ProjectPage;

     

    댓글