본문 바로가기
웹 프로그래밍/🌜꿈 일기장

[React] 꿈 일기 기록 사이트 제작 일지-11. 일기 검색 기능 추가

by 청량리 물냉면 2023. 9. 27.
반응형

일기 검색 코드는 간단하게 로직을 짠 뒤 필요한 부분을 수정해 가며 진행하기로 했다. 

 

🔍 일기 검색 코드 작성

  const diaryCtx = useContext(DiaryContext);
  const [inputText, setInputText] = useState("");

  const inputHandler = (e) => {
    let lowerCase = e.target.value.toLowerCase();
    setInputText(lowerCase);
  };

  const SearchedData = diaryCtx.diary.filter((it) => {
    if (inputText !== "") {
      return it.content.toLowerCase().includes(inputText);
    }
  });

 

전체 일기 중 입력창에 입력한 문자(inputText)를 포함하고 있는 일기를 검색하는 것이기 때문에, diary-context에서 전체 일기를 불러온다.

inputHandler는 입력창 input의 onChange에 연결해 놓은 함수이다.

혹시 영어를 입력하는 경우 입력한 내용을 모두 소문자로 바꾼 후에 lowerCase 변수에 저장한다. 이 lowerCase 값을 inputText라는 state에 저장한 뒤, inputText가 비어있지 않은 경우 전체 일기에서 inputText값을 포함한 일기만 필터링하여 searchedData에 담았다. 

 

  return (
    <div className="search">
      <input type="text" placeholder="Search" onChange={inputHandler} />
      {SearchedData && (
        <div className="searchResult">
          <ul>
            {SearchedData.map((item) => (
              <li key={item.id}>{item.content}</li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );

JSX 코드는 간단하게 검색한 결과를 화면에 출력해 주도록 작성했다.

 

 

💻 일기 내용 화면에 출력하기: useNavigate, useLocation을 이용한 페이지 이동과 데이터 전달

검색은 잘 되고 있기 때문에 이제 일기 검색한 내용을 본문에 띄우도록 코드를 수정한다. 

먼저 검색한 일기데이터만 모아 띄워줄 수 있는 일기 검색 결과 페이지를 생성했다. 👉 SearchResult.js

라우트에도 검색 페이지를 추가해 이동이 가능하도록 해준다. url은 /search로 설정했다.

일기 검색창 옆에는 버튼을 하나 달아 navigate로 검색 결과 페이지로 이동하도록 했다.

일기 검색 페이지에서는 props로 넘겨받은 일기 데이터들을 띄워주도록 작성하고 싶었다. 이를 위해서 인터넷에 페이지 이동 시 데이터도 넘겨주는 방법을 검색했고 useNavigate의 state로 데이터를 넘겨줄 수 있고 useLocation으로 데이터를 받을 수 있다는 사실을 알게 되었다. 

 

[React] 페이지 이동할 때, 데이터 전달하기

useNavagate 와 useLocation 훅을 이용하여 페이지 이동과 데이터 전달하기

velog.io

  return (
    <div className="search">
      <input type="text" placeholder="Search" onChange={inputHandler} />
      <Button
        type="dark-brown"
        text="검색"
        onClick={() => navigate("/search", { state: SearchedData })}
      />
      {/* {SearchedData && (
        <div className="searchResult">
          <ul>
            {SearchedData.map((item) => (
              <li key={item.id}>{item.content}</li>
            ))}
          </ul>
        </div>
      )} */}
    </div>
  );

SearchBar.js에서 useNavigate로 값을 전달했으니 SearchResult.js에서 useLocation을 이용해 값을 받아와 사용해 보겠다.

 

import { useLocation } from "react-router-dom";

const SearchResult = () => {
  const SearchedData = useLocation();
  console.log(SearchedData);
  return (
    <div>
      {SearchedData && (
        <div className="searchResult">
          <ul>
            {SearchedData.map((item) => (
              <li key={item.id}>{item.content}</li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );
};

export default SearchResult;

이 코드는 오류가 뜨는 코드이다.

대신 콘솔로 찍어보니 아래와 같이 데이터를 잘 받아오고 있음을 알 수 있다. 

SearchedData 대신 SearchedData.state를 써서 데이터를 받아오면 오류가 해결될 것으로 보인다.

오류 해결 👇

...
  const SearchResult = () => {
  const SearchedData = useLocation();
  console.log(SearchedData.state);
  return (
    <div>
      <div className="searchResult">
        <ul>
          {SearchedData.state.map((item) => (
            <li key={item.id}>{item.content}</li>
          ))}
        </ul>
      </div>
    </div>
  );
};

export default SearchResult;

state 내부에 데이터가 정상적으로 들어오고 있다. 

이미 SearchBar에서 빈 문자를 검색하지 못하게 필터링해주고 있기 때문에 SearchedData가 존재하는지 여부를 확인하는 코드는 제거했다. 

이제 넘겨받은 데이터를 화면에 뿌려주고 CSS 스타일링만 해주면 search 기능이 완성될 것이다.

전체적인 화면 구성과 기능은 DiaryItem 컴포넌트와 유사하기 때문에 DiaryItem 컴포넌트를 재사용해 화면에 데이터를 출력해줄 예정이다.

 

👀 일기 내용 화면에 출력하기: DiaryItem 컴포넌트를 재사용하여 데이터 출력하기

import { useLocation } from "react-router-dom";
import DiaryItem from "../diary/DiaryItem";

const SearchResult = () => {
  const SearchedData = useLocation();
  console.log(SearchedData.state);
  return (
    <div>
      <div className="searchResult">
        {SearchedData.state.map((it) => (
          <DiaryItem key={it.id} {...it} />
        ))}
      </div>
    </div>
  );
};

export default SearchResult;

검색 결과를 화면에 잘 출력해 주고 있다.

이제 상단 헤더와 전체적인 스타일링을 조금 더 손보고 해당 기능 구현을 마무리하겠다.

 

💫 일기 내용 화면에 출력하기: 마무리

검색 결과 상단에 어떤 검색어를 입력했는지 알려주면 좋을 것 같아서 state에 inputText를 추가로 전달했다.

      <Button
        type="dark-brown"
        text="검색"
        onClick={() =>
          navigate("/search", {
            state: { inputText, SearchedData },
          })
        }
      />

 

SearchReult 코드도 살짝 수정했다.

import { useLocation, useNavigate } from "react-router-dom";
import DiaryItem from "../diary/DiaryItem";
import Header from "../components/Header";
import Button from "../components/Button";

const SearchResult = () => {
  const location = useLocation();
  const navigate = useNavigate();

  return (
    <div>
      <Header
        leftBtn={
          <Button
            type="light-brown"
            text="뒤로 가기"
            onClick={() => navigate(-1)}
          />
        }
        headText={`'${location.state.inputText}' 검색 결과입니다`}
      />
      <div className="searchResult">
        {location.state.SearchedData.map((it) => (
          <DiaryItem key={it.id} {...it} />
        ))}
      </div>
    </div>
  );
};

export default SearchResult;

 

🚜 결과

 

💄  스타일링

 

 


COMMIT

 

:sparkles:일기 검색 기능 추가 · Yoonyesol/Dream_note@f2807c7

Yoonyesol committed Sep 27, 2023

github.com

 

반응형