Coder Social home page Coder Social logo

hello-world's Introduction

hello-world's People

Contributors

joonfluence avatar

Stargazers

 avatar

Watchers

 avatar

hello-world's Issues

컴포넌트 사이에 다른 데이터를 넣는 방법

문제상황

아래 다이어그램과 같이, 일반 데이터 3개 당 광고 데이터 1개를 중간에 넣어야 한다.

일반 - 일반 - 일반 - 광고 - 일반 - ...

짐작

  1. Post 데이터 3개를 받아오면, AD 데이터 1개를 받아오는 방식을 택하자.
  • 각각 API의 limit을 3과 1로 지정해주면 될 것이다.

api.get("/api/list", {
    params: {
      page: 1,
      ord: "asc",
      category: [1],
      limit: 3,
    },
  });


api.get("/api/ads", {
    params: {
      page: 1,
      limit: 1,
    },
  });

=> 이렇게 할 경우, limit의 값을 바꿔야 하므로 다른 방법이 좋을 것 같다.

  1. 기존에 관리하던 state를 통합시키면 어떨까?
  const [list, setList] = useState([]);
  const [adList, setAdList] = useState([]);

  const fetchPostList = async (pageNum, order, categoryNum, limitNum) => {
    let temp = await getPostList(pageNum, order, categoryNum, limitNum);
    setList(temp);
  };

  const fetchADList = async (pageNum, limitNum) => {
    let temp = await getADList(pageNum, limitNum);
    setAdList(temp);
  };

현재는 다음과 같이 state들을 관리하고 있다. 이들을 하나로 합치고 해당 값을 넣어주면 어떨까? ad의 값을 arr[3], arr[7], arr[11]... 위치에 넣어주는 것이다.

참조링크 (원하는 배열 인덱스에 값을 추가하는 방법)

https://javascript.plainenglish.io/insert-an-element-in-specific-index-in-javascript-array-9c059e941a67

https://stackoverflow.com/questions/45147420/insert-object-into-array-at-specific-index-in-react/45147550


function addAfter(array, index, newItem) {
    return [
        ...array.slice(0, index),
        newItem,
        ...array.slice(index)
    ];
}

=> 불변성을 유지하면서 데이터를 원하는대로 조작할 수 있을 것이다. 

  • 피드 글과 광고 글을 합쳐서 feed라는 state를 만들었고 광고 포스팅 1개의 값을 4번째에 넣는 것은 성공했다. 그런데 이걸 반복해서 실행하는데, 어려움을 겪고 있다. 어떻게하면 반복적으로 실행시킬 수 있을까?

=> 일반 - 일반 - 일반 - 광고 - 일반 - 일반 - 일반 - 광고 - 일반 - 일반 - 일반 - 광고 - 일반 - 일반 - 일반 - 광고 - 일반 - 일반 - 일반 - 광고 - 일반 - 일반 - 일반 - 광고 - 일반 - 일반 - 일반 - 광고 - 일반 - 일반 - 일반 - 광고 - 일반 - 일반 - 일반 - 광고

  • 일반 - 일반 - 일반 - 광고 => 이 구조가 계속적으로 반복되고 있다. 이를 반복해서 넣어주면 될 것 같다. 이 때 인덱스를 잘 관리해주면 되지 않을까?

  • 이렇게하면 10개씩 렌더링하기가 어려워진다. 반복되는 구조를 가져가면서도 10개씩 렌더링하는 부분에서 막히고 있다.

처음으로 돌아와서 피드와 광고 글을 합치지말고, 피드 컨텐츠의 인덱스가 3, 7, 11, 15 ... 와 같은 index일 경우, 광고 글을 추가해주는 것이 어떨까?

  const [type, setType] = useState("1");
  const [limit, setLimit] = useState(10);
  const [list, setList] = useState([]);
  const [adList, setAdList] = useState([]);
  const [feedIndex, setFeedIndex] = useState(0);
  const [adIndex, setAdIndex] = useState(0);
  const [feed, setFeed] = useState([]);

const sliceContent = (index, adIndex, newItem) => {
    let temp = [
      ...list.slice(index, index + 3),
      ...newItem.slice(adIndex, adIndex + 1),
      ...list.slice(index + 3, index + 6),
      ...newItem.slice(adIndex + 1, adIndex + 2),
      ...list.slice(index + 6, index + 9),
      ...newItem.slice(adIndex + 2, adIndex + 3),
    ];
    return temp;
  };

  useEffect(() => {
    fetchPostList(1, "asc", Number(type), limit);
    fetchADList(1, limit);
    setFeed(sliceContent(Number(feedIndex), adIndex, adList));
  }, [type, limit]);

참조

https://javascript.info/iterable

  • Feed를 현재 다음과 같이 변경하고 있다. 이 방식이 잘못되었다. 개선해보자. setFeed로 값을 변경할 것이 아니라, 10개씩 추가로 로드할 때 해당 배열에 객체를 추가로 넣어주는 방법을 택하자. concat 메소드를 쓰면 될 것 같다.

  • 배열 안에 객체를 넣으려고 하지만 push 외에는 방법을 모르겠다.
    => push를 사용하는 것은 맞으나, 그러려면 temp를 전역으로 관리하여야 할 것이다. 왜냐면 컴포넌트 안에서 관리할 경우, 새롭게 렌더링되는 시점마다 초기화되기 때문이다. 근데 그러면 너무 복잡해지는 문제가 있다. (일단은 다른 기능들부터 구현하자)

  • 이 방식으로 진행하면 12개씩 콘텐츠가 로드될 것이다. 이는 요구사항과 다르다.

=> 패턴을 분석해보니, 2가지 패턴이 반복됨. 따라서 패턴에 따라, 코딩을 해주었음.


  const sliceContent = (index, adIndex, newItem) => {
    let temp = [];
    if (index % 15 === 0) {
      console.log("실행됨");
      temp = [
        ...list.slice(index, index + 3),
        ...newItem.slice(adIndex, adIndex + 1),
        ...list.slice(index + 3, index + 6),
        ...newItem.slice(adIndex + 1, adIndex + 2),
        ...list.slice(index + 6, index + 8),
      ];

      setFeedIndex(feedIndex + 8);
      setAdIndex(adIndex + 2);

      console.log("feedIndex", feedIndex);
      console.log("adIndex", adIndex);
    } else {
      temp = [
        ...list.slice(index, index + 1),
        ...newItem.slice(adIndex, adIndex + 1),
        ...list.slice(index + 1, index + 4),
        ...newItem.slice(adIndex + 1, adIndex + 2),
        ...list.slice(index + 4, index + 7),
        ...newItem.slice(adIndex + 2, adIndex + 3),
      ];
      setFeedIndex(feedIndex + 7);
      setAdIndex(adIndex + 3);

      console.log("feedIndex", feedIndex);
      console.log("adIndex", adIndex);
    }
    return temp;
  };

  • slice한 데이터들을 state에 저장하는 문제만 해결하면 될 것임.

=> 인덱스 변경이 너무 잦아, 원하는 값을 불러오지 못하고 있다. 이를 막기 위해, 인덱스를 하나로 통일할 필요가 있다. 이에 관해서 정리해보자.

  const sliceContent = (limit) => {
    let temp = [];
    let oddNum = 0;
    let oddNumber = 0;
    let evenNumber = 0;
    let oddAdNum = 0;
    let evenAdNum = 0;

    if (limit % 20 !== 0) {
      // 10, 30, 50, 70, 90, 110 ...
      // 2, 3, 4, 5, ...
      // 10, 15, 20, 25 ...
      // 0, 5, 10, 15 ...
      console.log("실행됨");
      oddNum = Math.floor(limit / 20) + 2;
      oddAdNum = Math.floor(limit / 20) * 5;
      oddNumber = oddNum * 5;

      temp = [
        ...list.slice(limit - oddNumber, limit - oddNumber + 3),
        ...adList.slice(oddAdNum, oddAdNum + 1),
        ...list.slice(limit - oddNumber + 3, limit - oddNumber + 6),
        ...adList.slice(oddAdNum + 1, oddAdNum + 2),
        ...list.slice(limit - oddNumber + 6, limit - oddNumber + 8),
      ];
    } else {
      // 20, 40, 60, 80 ...
      // 2, 3, 4, 5, ...
      // 12, 17, 22, 27 ...
      // 2, 7, 12, 17 ...
      console.log("실행됨2");
      oddNum = Math.floor((limit - 10) / 20) + 2;
      oddAdNum = Math.floor((limit - 10) / 20) * 5;
      oddNumber = oddNum * 5;

      evenNumber = oddNumber + 2;
      evenAdNum = oddAdNum + 2;

      temp = [
        ...list.slice(limit - evenNumber, limit - evenNumber + 1),
        ...adList.slice(evenAdNum, evenAdNum + 1),
        ...list.slice(limit - evenNumber + 1, limit - evenNumber + 4),
        ...adList.slice(evenAdNum + 1, evenAdNum + 2),
        ...list.slice(limit - evenNumber + 4, limit - evenNumber + 7),
        ...adList.slice(evenAdNum + 2, evenAdNum + 3),
      ];
    }
    return temp;
  };

  • limit 값을 받아, 내부적으로 계산하여 해결하였음.

  • 기능은 작동되나 기존 방식이 너무 복잡하여, 코드 가득성이 떨어지고 컴포넌트 렌더링 dependency가 얽혀있어 오류가 잦으므로 코드를 수정할 것.

처음으로 돌아와서 피드와 광고 글을 합치지말고, 피드 컨텐츠의 인덱스가 3, 7, 11, 15 ... 와 같은 index일 경우, 광고 글을 추가해주는 것이 어떨까?

(..실제로 우려한 일이 현실이 되었다 크흠)

=> 배열의 map 함수에 index 값을 알 수 있으므로, 불러온 글 리스트의 특정 인덱스에 광고를 추가하는 방식으로 변경해보자.


  const checkIsAd = (i) => i % 4 === 2;

  // 중략

  return (
    <main>
      <div>
        <Nav />
        <div className="main__wrapper">
          <div className="main__login">
            <span>로그인</span>
          </div>
          <div className="main__container">
            <Filter
              type={type}
              setType={setType}
              order={order}
              setOrder={setOrder}
            />
            {list.map((item, i) => (
              <>
                <div className="main__content--wrapper" key={item.id}>
                  <Link to={`/` + item.id}>
                    <div className="main__header">
                      <div>
                        <div className="main__header--container">
                          <div className="main__header--category">
                            {item.category_id === 1
                              ? CATEGORY_ID_1
                              : item.category_id === 2
                              ? CATEGORY_ID_2
                              : CATEGORY_ID_3}
                          </div>
                          <div className="main__header--id">{item.id}</div>
                        </div>
                        <div className="main__header--container">
                          <div className="main__header--userID">
                            {item.user_id}
                          </div>
                          <div className="main__header--date">
                            created_at({item.created_at.substring(0, 10)})
                          </div>
                        </div>
                      </div>
                    </div>
                    <div className="main__content--container">
                      <h3 className="main__content--title">{item.title}</h3>
                      <div className="main__content--description">
                        {item.contents}
                      </div>
                    </div>
                  </Link>
                </div>
                {checkIsAd(i) ? <Ad item={adList[(i - 2) / 4]} /> : null}
              </>
            ))}
          </div>
        </div>
      </div>
    </main>
  );

  • feed 대신 list를 렌더링해주고, map의 index를 사용하여 원하는 위치에 광고를 삽입해줬음.

  • 이렇게 해주니, 횔씬 코드가 깔끔해지고 불필요한 데이터 소모도 줄일 수 있게 되었다.

피드 콘텐츠 불러오기

[피드 컨텐츠]

  • 글자 수가 많으면 자르고 생략기호(...) 표시

  • 컨텐츠 불러오기 (infinite-loading)

    • 처음에 10개만 불러오기
    • 스크롤이 최하단에 닿을 때마다 리스트에 10개씩 추가
      => react virtual 사용하라는 의미인 것 같다. (아닐 수도 있다.)
  • API를 통해 일단 화면에 데이터를 전부 불러오자 (V)

[axios]
우선 axios로 해당 데이터들을 불러오자.
작동하지 않는다.

가설 : 헤더가 잘못된 것 같다.

  1. header: "Accept: application/json" (X)
  2. headers: { Accept: "application/json" } (X)
  3. headers: { "Content-Type": "application/json" } (X)

###"strict-origin-when-cross-origin" 오류 발생.
http 요청에선 무엇이 문제인지 모르겠다.
proxy 설정해서 처리해보자.
=> 이것도 처리되지 않았다. 결국, 네트워크의 문제는 아닌 것 같다.

가설 : params를 수정해서 입력해보자.

api.get("/api/list", {
      params: {
        page: 1,
        ord: "asc",
        category: [1],
        limit: 10,
      },
    });

axios의 params를 입력하니, 정확하게 처리됐다.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.