본문 바로가기

CodeSoom- React 13기

[코드숨] 리액트 13기 -6강/과제1 제출코드 참고(레스토랑 상세 페이지 구현하기)

* react-router-dom 설치

 

 


GET http://localhost:8080/test/main.js net::ERR_ABORTED 404 (Not Found) 오류 해결

클릭시 랜더링되지만 주소창에 url통해서는 안들어가지는 오류 발생

>>해결:

/절대 경로 로 설정해야 url 입력시에도 페이지가 랜더링됨

 

아니면 head태그 안에 <base href="/"> 를 추가해서 해결하는 방법도 있음

 

 

net::ERR_ABORTED 404 (Not Found) 에러

정말 느닺없는 에러였다. 나는 잘만 작동하는 html이 갑자기 말썽이었다. 콘솔창 에러가 말씀하시길 나는 이유를 알 수가 없었다. "이상하다. 나는 main.js를 설정한 적이 없는데 이게 왜있지? "그런

velog.io

 

 

<base>: The Document Base URL element - HTML: HyperText Markup Language | MDN

The <base> HTML element specifies the base URL to use for all relative URLs in a document. There can be only one <base> element in a document.

developer.mozilla.org

 


▼ 과제 제출 코드 참고

 

 

 

App.jsx

import {
  Routes,
  Route,
  Link,
} from 'react-router-dom';

import HomePage from './HomePage';
import AboutPage from './AboutPage';
import RestaurantsPage from './RestaurantsPage';
import RestaurantsInfoPage from './RestaurantsInfoPage';
import NotFoundPage from './NotFoundPage';

export default function App() {
  return (
    <div>
      <header>
        <h1>
          <Link to="/">헤더 영역</Link>
        </h1>
      </header>
      <Routes>
        <Route exact path="/" element={<HomePage />} />
        <Route path="/about" element={<AboutPage />} />
        <Route path="/restaurants" element={<RestaurantsPage />} />
        <Route path="/restaurants/:id" element={<RestaurantsInfoPage />} />
        <Route path="*" element={<NotFoundPage />} />
      </Routes>
    </div>
  );
}

 

App.test.jsx

import { MemoryRouter } from 'react-router-dom';

import { render } from '@testing-library/react';

import { useDispatch, useSelector } from 'react-redux';

import App from './App';

import restaurants from '../fixtures/restaurants';
import categories from '../fixtures/categories';
import regions from '../fixtures/regions';

describe('App', () => {
  beforeEach(() => {
    const dispatch = jest.fn();

    useDispatch.mockImplementation(() => dispatch);

    useSelector.mockImplementation((selector) => selector({
      regions,
      categories,
      restaurants,
    }));
  });

  const renderApp = ({ path }) => render((
    <MemoryRouter initialEntries={[path]}>
      <App />
    </MemoryRouter>
  ));

  context('올바른 경로일 경우', () => {
    it('"/"일 때, HomePage가 랜더링된다', () => {
      const { container } = renderApp({ path: '/' });

      expect(container).toHaveTextContent('HomePage');
    });

    it('"/about"일 때, AboutPage가 랜더링된다', () => {
      const { container } = renderApp({ path: '/about' });

      expect(container).toHaveTextContent('About 페이지입니다.');
    });

    it('"/restaurants"일 때, RestaurantsPage가 랜더링된다', () => {
      const { container } = renderApp({ path: '/restaurants' });

      expect(container).toHaveTextContent('김밥제국');
    });
  });

  context('잘못된 경로일 경우', () => {
    it('NotFoundPage가 랜더링된다', () => {
      const { container } = renderApp({ path: '/xxx' });

      expect(container).toHaveTextContent('404 Not Found Page');
    });
  });
});

 

 

 

 

 

 

 

 

 

actions.test.jsx

import thunk from 'redux-thunk';

import configureStore from 'redux-mock-store';

import restaurantInfo from '../fixtures/restaurantInfo';

import {
  loadInitialData,
  setRegions,
  setCategories,
  loadRestaurants,
  setRestaurants,
  loadRestaurantsInfo,
  setRestaurantInfo,
} from './actions';

const middlewares = [thunk];
const mockStore = configureStore(middlewares);

jest.mock('./services/api');

describe('actions', () => {
  let store;

  describe('loadInitialData', () => {
    beforeEach(() => {
      store = mockStore({});
    });

    it('runs setRegions and setCategories', async () => {
      await store.dispatch(loadInitialData());

      const actions = store.getActions();

      expect(actions[0]).toEqual(setRegions([]));
      expect(actions[1]).toEqual(setCategories([]));
    });
  });

  describe('loadRestaurants', () => {
    context('with selectedRegion and selectedCategory', () => {
      beforeEach(() => {
        store = mockStore({
          selectedRegion: { id: 1, name: '서울' },
          selectedCategory: { id: 1, name: '한식' },
        });
      });

      it('runs setRestaurants', async () => {
        await store.dispatch(loadRestaurants());

        const actions = store.getActions();

        expect(actions[0]).toEqual(setRestaurants([]));
      });
    });

    context('without selectedRegion', () => {
      beforeEach(() => {
        store = mockStore({
          selectedCategory: { id: 1, name: '한식' },
        });
      });

      it('does\'nt run any actions', async () => {
        await store.dispatch(loadRestaurants());

        const actions = store.getActions();

        expect(actions).toHaveLength(0);
      });
    });

    context('without selectedCategory', () => {
      beforeEach(() => {
        store = mockStore({
          selectedRegion: { id: 1, name: '서울' },
        });
      });

      it('does\'nt run any actions', async () => {
        await store.dispatch(loadRestaurants());

        const actions = store.getActions();

        expect(actions).toHaveLength(0);
      });
    });
  });

  describe('loadRestaurantsInfo', () => {
    beforeEach(() => {
      store = mockStore({
        restaurantInfo,
      });
    });

    it('setRestaurantInfo를 실행한다', async () => {
      await store.dispatch(loadRestaurantsInfo());

      const actions = store.getActions();

      expect(actions[0]).toEqual(setRestaurantInfo([]));
    });
  });
});

 

 

 

 

 

webpack.config.js는 아래로도 사용 가능