인프런 커뮤니티 질문&답변
TabBar.js 오류가 자꾸 발생하는데 무슨이유인지 모르겠습니다;;
해결된 질문
작성
·
162
0
전체 사진 처음 화면은 로딩 되서 잘나오는데 펭귄이나 다른탭을 클릭하면 아래와 같은 오류가 나오는데 TabBar.js onclick 함수가 아니라는데;; 왜이런건지 함수가 맞는데 아래에 제가 작성한 코드 입니다 검토 좀 부탁드립니다.^^;;
TabBar.js
export default function TabBar({ $app, initialState, onClick }) {
  // TabBar 클래스를 생성합니다. 초기값과 클릭 이벤트를 받습니다.
  this.state = initialState; // 초기값 설정
  this.onClick = onClick; // 클릭 이벤트 설정
  this.$target = document.createElement("div"); // 새로운 div 요소를 생성합니다.
  this.$target.className = "tab-bar"; // div 요소에 클래스 이름을 추가합니다.
  $app.appendChild(this.$target); // $app 요소에 div 요소를 추가합니다.
  this.template = () => {
    let temp = `<div id="all">전체</div><div id="penguin">펭귄</div>
        <div id ="koala">코알라</div><div id ="panda">판다</div>`; // 전체 탭을 추가합니다.
    return temp; // temp를 반환합니다.
  };
  this.render = () => {
    // 렌더링 함수
    this.$target.innerHTML = this.template(); // div 요소의 innerHTML을 template 함수의 반환값으로 설정합니다.
    let $currentTab = document.getElementById(this.state); // 현재 탭을 선택합니다.
    // $currentTab ? ($currentTab.className = "clicked") : ""; // 현재 탭이 존재하면 clicked 클래스를 추가합니다. 없으면 변화없음.
    $currentTab && ($currentTab.className = "clicked"); // && 연산자를 사용하여 현재 탭이 존재하면 clicked 클래스를 추가합니다.
    const $tabBar = this.$target.querySelectorAll("div"); // 모든 div 요소를 tabBar 요소에 담아온다.
    $tabBar.forEach((elm) => {
      elm.addEventListener("click", () => {
        // 각 div 요소에 클릭 이벤트 리스너를 추가합니다.
        this.onClick(elm.id); // 클릭한 div 요소의 id를 onClick 함수에 전달합니다.
      });
    });
  };
  this.setState = (newState) => {
    // state를 변경하는 함수
    this.state = newState; // state를 새로 받은 newState로 업데이트합니다.
    this.render(); // state가 변경되면 렌더링 함수를 다시 호출하여 화면을 업데이트합니다.
  };
  this.render(); // 렌더링 함수를 호출합니다.
}
App.js
import TabBar from "./components/TabBar.js"; // TabBar.js 파일을 불러옵니다.
import Content from "./components/Content.js"; // Content.js 파일을 불러옵니다.
import { request } from "./components/api.js"; // api.js 파일을 불러옵니다.
export default function App($app) {
  // App 생성자 함수를 생성합니다.
  // $app은 App 컴포넌트가 렌더링될 DOM 요소입니다.
  this.state = {
    //state 초기값 설정
    currentTab: "all", // 탭 초기값 설정 tabbar 컴포넌트에 전달할 현재 탭 데이터
    photos: [], // 사진 초기값 설정 content 컴포넌트에 전달할 사진 데이터
  };
  const tabbar = new TabBar({
    $app, // App 컴포넌트가 렌더링될 DOM 요소를 전달합니다.
    initialState: "", // 초기값 설정
    oncClick: async (name) => {
      // 클릭 이벤트 설정 변경값을 currentTab에 저장
      this.setState({
        // 클릭한 탭의 데이터를 state에 저장합니다.
        ...this.State, // 기존 state를 복사합니다. 스프레드 연산자
        currentTab: name, // 클릭한 탭의 이름을 currentTab에 저장합니다.
        photos: await request(name === "all" ? "" : name), // 클릭한 탭의 새로운 사진을 request 이름으로 함수를 불러와 저장합니다.
        // request 함수는 비동기 함수로 async await를 사용하여 데이터를 받아옵니다.
      });
    },
  });
  const content = new Content({
    $app, // App 컴포넌트가 렌더링될 DOM 요소를 전달합니다.
    initialState: [], // 초기값 설정
  });
  this.setState = (newState) => {
    // 업데이트 값을 newState로 받습니다.
    this.state = newState; // state를 새로 받은 newState로 업데이트합니다.
    tabbar.setState(this.state.currentTab); // tabbar 컴포넌트에 state를 전달합니다.
    content.setState(this.state.photos); // content 컴포넌트에 state를 전달합니다.
  };
  const init = async () => {
    //웹페이지가 로드되면 실행되는 함수
    try {
      const initialPhotos = await request(); // request 함수를 불러와 initialPhotos에 저장합니다.
      this.setState({
        // state를 initialPhotos로 업데이트합니다.
        ...this.state, // 기존 state를 복사합니다. 스프레드 연산자
        photos: initialPhotos, // initialPhotos를 photos에 저장합니다.
      });
    } catch (err) {
      console.log(err);
    }
  };
  init(); // 웹애플리케이션이 실행될때 init 함수를 실행합니다.
}
index.js
import App from "../src/App.js";
const $app = document.getElementById("app");
new App($app);
api.js
const API_URL = "https://animal-api-two.vercel.app"; // 이미지 url을 변수에 저장
// const $content = document.querySelector("div.content"); //(api 불러오는 코드만 남겨놓기 위해 삭제제)
// let template = []; // (api 불러오는 코드만 남겨놓기 위해 삭제제)
//API
export const request = async (name) => {
  const res = await fetch(name ? `${API_URL}/${name}` : API_URL); // fetch 함수를 사용하여 API_URL을 호출합니다. name이 있으면 name을 호출합니다. 없으면 API_URL을 호출합니다.
  try {
    if (res) {
      let data = await res.json();
      return data.photos;
    }
  } catch (err) {
    console.log(err);
  }
};
index.html
<!DOCTYPE html>
<head>
  <title>Animal Album</title>
  <meta charset="UTF-8" />
  <link rel="stylesheet" href="../project2/src/style.css" />
  <script type="module" src="../project2/src/index.js" defer></script>
</head>
<body>
  <div id="app">
    <!-- TAB BAR -->
    <!-- CONTENT -->
  </div>
</body>
content.js
export default function Content({ $app, initialState }) {
  this.state = initialState;
  this.$target = document.createElement("div");
  this.$target.className = "Content";
  $app.appendChild(this.$target);
  this.template = () => {
    let temp = [];
    if (this.state) {
      this.state.forEach((elm) => {
        temp += `<img src="${elm.url}"></img>`;
      });
    }
    return temp;
  };
  this.render = () => {
    this.$target.innerHTML = this.template();
  };
  this.setState = (newState) => {
    this.state = newState;
    this.render();
  };
  this.render();
}
콘솔 오류코드
TabBar.js:26 Uncaught TypeError: this.onClick is not a function
    at HTMLDivElement.<anonymous> (TabBar.js:26:14)답변 2
1
1
안녕하세요, 인프런 AI 인턴입니다. musful님, 질문 주셔서 감사합니다.
열거하신 오류는 TabBar.js의 onClick 이벤트 리스너 관련 설정에서 발생하는 것으로 보입니다. TypeError: this.onClick is not a function이라는 오류는 onClick이 정의되었지만 제대로 함수로 전달되지 않았기 때문에 나타납니다.
문제 해결:
- 오타 확인:
 - App.js에서- TabBar컴포넌트를 생성할 때,- oncClick대신- onClick으로 명명되었는지 확인하세요. 코드에서 오타가 있는 것 같습니다.
 
 
   const tabbar = new TabBar({
     $app,
     initialState: "",
     onClick: async (name) => { // 여기를 확인해주세요.
       this.setState({
         ...this.state,
         currentTab: name,
         photos: await request(name === "all" ? "" : name),
       });
     },
   });
- 함수 전달 확인:
 - onClick속성에 전달되는 것이 반드시 함수이어야 하며, 적절히- App.js내에서 정의된 함수가 전달되었는지 확인하십시오. 이 경우- async (name) => { ... }로 설정된 것이 맞습니다.
 
 
추가 조치:
- 각 클래스와 함수에서 this가 기대한 대로 바인딩되고 있는지 확인하십시오. 특히 이벤트 핸들러를 화살표 함수(name) => { ... }형태로 사용하면this가 사전에 정의된 컨텍스트로 바인딩됩니다.
 
관련 질문 URL:
- “TabBar에서 발생할 수 있는 미세한 문제들에 대해 설명/해결한 포스트” - 유사한 코드 패턴에서 자주 발생하는 문제를 들여다볼 수 있는 게시글입니다.
 
이런 방식으로 코드의 각종 부분을 면밀히 검토하여 이상이 없도록 한다면 문제 해결에 도움이 될 것입니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.








해결하셔서 다행입니다!!