관리 메뉴

프로그래밍 삽질 중

React로 필터 만들기(checkbox) (1) 본문

과거 프로그래밍 자료들/React

React로 필터 만들기(checkbox) (1)

평부 2022. 5. 23. 22:17

* '따라하며 배우는 노드, 리액트 시리즈 - 쇼핑몰 사이트 만들기' 강의 참고

* react -> node.js로 이미지 및 정보 저장하기

* mongoDB에 저장하는 것까지 확인

* 저장된 값의 정보 바꿔야함 -> 필터 적용시켜 찾기 위함

 

 

[1.필터 만들기 전 사전 작업]

 

1. MongoDB 수정

mongoDB season 항목 추가(int 타입)

 

[Server]

1. review/Data.js

 

const mongoose = require("mongoose");

const dataSchema = mongoose.Schema(
  {
    title: {
      type: String,
    },
    description: {
      type: String,
      maxlength: 50,
    },
    images: {
      type: Array,
      default: [],
    },
    season: { //추가
      type: Number,
      default: 1,
    },

    //시간 자동 업데이트
  },
  { timestamps: true }
);

const Data = mongoose.model("Data", dataSchema);

module.exports = { Data };

 

[Client]

Review/DataUpload.js

 

import React, { useState } from "react";
import { Button, Form, Input } from "antd";
import axios from "axios";
import { useNavigate } from "react-router-dom";
import FileUpload from "./FileUpload";

const { TextArea } = Input;

//추가1
const Seasons = [
  { key: 1, value: "봄" },
  { key: 2, value: "여름" },
  { key: 3, value: "가을" },
  { key: 4, value: "겨울" },
];

function DataUpload() {
  const [Title, setTitle] = useState("");
  const [Description, setDescription] = useState("");
  const [Images, setImages] = useState([]);
  //추가2 기본값 1로 둠
  const [Season, setSeason] = useState(1);

  const navigate = useNavigate();

  const titleChangeHandler = (event) => {
    setTitle(event.currentTarget.value);
  };

  const descriptionChangeHandler = (event) => {
    setDescription(event.currentTarget.value);
  };

	//추가3
  const seasonHandler = (event) => {
    setSeason(event.currentTarget.value);
  };

  const updateImages = (newImages) => {
    setImages(newImages);
  };


  const submitHandler = (event) => {
    //페이지 자동 리프레시 되는 것 막음
    event.preventDefault();

    //값이 하나라도 비면 오류
    if (!Title || !Description || !Images || !Seasons) {
      return alert("모든 값을 작성해야 합니다.");
    }

    //값을 다 채우면 서버 request로 보낸다
    const body = {
      //로그인된 사람의 아이디
      title: Title,
      description: Description,
      images: Images,
      season: Season,
    };

    console.log(Title, Description, Images);

    axios.post("/api/data", body).then((response) => {
      if (response.data.success) {
        alert("상품 업로드에 성공했습니다.");
        navigate("/review");
      } else {
        alert("상품 업로드에 실패했습니다.");
      }
    });
  };

  return (
    <div
      style={{
        display: "flex",
        justifyContent: "center",
        alignItems: "center",
        width: "100%",
        height: "100vh",
      }}
    >
      <div style={{ textAlign: "center", marginBottom: "2rem" }}>
        <br />
        <br />
        <br />
        <h2>계절 관련 업로드</h2>
        <Form onSubmitCapture={submitHandler}>
          {/* FileUpload에서 refreshFunction으로 제어 */}
          <FileUpload refreshFunction={updateImages} />
          <label>이름</label>
          <Input onChange={titleChangeHandler} value={Title} />
          <br />
          <br />
          <label>설명</label>
          <TextArea onChange={descriptionChangeHandler} value={Description} />
          <br />
          <br />
          //추가 4
          <select onChange={seasonHandler}>
            {Seasons.map((city) => (
              <option key={city.key} value={city.key}>
                {city.value}
              </option>
            ))}
          </select>

          <br />
          <br />
          <div>
            <Button onClick={submitHandler}>확인</Button>
          </div>
        </Form>
      </div>
    </div>
  );
}

export default DataUpload;

 

 

* 결과 

 

 

 

[2.필터 만들기 설정하기]

 

[Client]

Sections/Data.js & DataCheckbox.js

 

//Data.js
const seasons = [
  { _id: 1, name: "봄" },
  { _id: 2, name: "여름" },
  { _id: 3, name: "가을" },
  { _id: 4, name: "겨울" },
];

export { seasons };

//DataCheckbox.js
import React, { useState } from "react";
import { Collapse, Checkbox } from "antd";

const { Panel } = Collapse;

function DataCheckbox(props) {
  //list로 값 전달

  const [Checked, setChecked] = useState([]);

  const handleToggle = (value) => {
    //누른 index 번호 확인
    const currentIndex = Checked.indexOf(value);
    //이미 눌러졌다면
    const newChecked = [...Checked];

    //눌러지지 않다면(항목은 총 1, 2, 3, 4를 가지는데 값이 없으면 indexOf가 -1로 표기)
    if (currentIndex === -1) {
      newChecked.push(value);
    } else {
      //빼주고 state를 넣어준다
      //splice : 눌러진 index의 값이 지워짐
      newChecked.splice(currentIndex, 1);
    }
    setChecked(newChecked);
  };

  const renderCheckboxList = () =>
    props.list &&
    props.list.map((value, index) => (
      <React.Fragment key={index}>
        <Checkbox
          onChange={() => handleToggle(value._id)}
          type="checkbox"
          checked={Checked.indexOf(value._id) === -1 ? false : true}
        />
        <span>{value.name}</span>
      </React.Fragment>
    ));

  return (
    <div>
      <Collapse style={{ height: "100%", width: "500px", marginLeft: "14.8%" }}>
        <Panel header="Seasons" key="1">
          {renderCheckboxList()}
        </Panel>
      </Collapse>
    </div>
  );
}

export default DataCheckbox;

 

 

[Client]

ShowAllData.js

 

import axios from "axios";
import React, { useEffect, useState } from "react";
import { Card, Row, Col } from "antd";
import ImageSlider from "./Sections/ImageSlider";

//불러오기
import { seasons } from "./Sections/Datas";
import DataCheckbox from "./Sections/DataCheckbox";

const { Meta } = Card;

function ShowAllData() {
  const [Datas, setDatas] = useState([]);
  //화면에 보여주는 이미지 수 제어
  const [Start, setStart] = useState(0);
  const [End, setEnd] = useState(6);

  //더보기 버튼 안 보이게 하기
  const [LimitImage, setLimitImage] = useState(0);

  useEffect(() => {
    let body = {
      start: Start,
      end: End,
    };

    commonAxios(body);
  }, []);

  //더 보기에 두 번 들어가기 때문에 따로 분리
  const commonAxios = (body) => {
    //post에 info값 넣을 것
    axios.post("/api/data/list", body).then((response) => {
      if (response.data.success) {
        // console.log(response.data);

        if (body.showMore) {
          setDatas([...Datas, ...response.data.dataInfo]);
        } else {
          setDatas(response.data.dataInfo);
        }
        setLimitImage(response.data.limitImage);
      } else {
        alert("상품을 가져오는데 실패했습니다.");
      }
    });
  };

  const showMoreData = () => {
    let start = Start + End;

    let body = {
      start: start,
      end: End,
      showMore: true,
    };

    //더 보기 버튼을 눌렀을 때 이전 정보도 같이 보여줘야 함
    commonAxios(body);
    setStart(start);
  };

  const renderCard = Datas.map((data, index) => {
    return (
      <div style={{ display: "Grid", placeItems: "center" }}>
        <Col lg={4} md={6} xs={16} key={index}>
          <Card
            style={{
              width: "350px",
              height: "20%",
              position: "relative",
              right: "50%",
            }}
            //ImageSlider에 images로 정보 전달
            cover={<ImageSlider images={data.images} />}
          >
            <Meta
              title={data.title}
              description={`$${data.description}`}
            ></Meta>
          </Card>
        </Col>
      </div>
    );
  });

  return (
    <div style={{ width: "100%", margin: "0" }}>
      <br />
      <br />
      <br />
      <br />
      <h2 style={{ textAlign: "center" }}>DB에 저장한 거 확인하기</h2>

      {/* checkBox 불러오기 */}
      <Col lg={10} xs={20} style={{ position: "relative", left: "8.5%" }}>
        <DataCheckbox list={seasons} />
      </Col>

      {/* card */}
      <div style={{ width: "85%", margin: "1rem auto" }}>
        <Row gutter={[20, 20]}>{renderCard}</Row>
      </div>

      {LimitImage >= End && (
        <div style={{ display: "flex", justifyContent: "center" }}>
          <button style={{}} onClick={showMoreData}>
            더 보기
          </button>
        </div>
      )}
    </div>
  );
}

export default ShowAllData;

 

 

* 결과