티스토리 뷰

App.js

import React from 'react';
import './App.css';
import './global-style.css';
// TODO - react-router-dom을 설치 후, import 구문을 이용하여 BrowserRouter, Routes, Route 컴포넌트를 불러오세요.
import { BrowserRouter, Routes, Route} from "react-router-dom";
import Sidebar from './Sidebar';
import Tweets from './Pages/Tweets';
// TODO - import문을 이용하여 MyPage, About 컴포넌트를 불러오세요.
import MyPage from './Pages/MyPage';
import About from './Pages/About';

const App = () => {
  return (
   
    <div>
      {/* TODO - BrowserRouter 컴포넌트를 작성합니다. */}
      <BrowserRouter>
        <div className="App">
          <main>
            <Sidebar />
            <section className="features">
              <Routes>
              <Route path="/" element={<Tweets />} /> 
                <Route path="/about" element={<About />} />
                <Route path="/mypage" element={<MyPage />} />
              </Routes>
            </section>
          </main>
        </div>
        </BrowserRouter>
    </div>
  );
};

// ! 아래 코드는 수정하지 않습니다.
export default App;

Mypage.js

import React from "react";
import { dummyTweets } from "../static/dummyData";
import "./MyPage.css";
// ! 위 코드는 수정하지 않습니다.

// TODO - import문을 이용하여 Footer 컴포넌트를 불러옵니다.
import Footer from '../Footer';

const MyPage = () => {
  // TODO - filter 메소드를 이용하여 username이 kimcoding인 요소만 있는 배열을 filteredTweet에 할당합니다.
  const filteredTweets = dummyTweets.filter( (tweet) => {
    return tweet.username === "kimcoding";
  });

  return (
    <section className="myInfo">
      <div className="myInfo__container">
        <div className="myInfo__wrapper">
          <div className="myInfo__profile">
            <img src={filteredTweets[0].picture} />
          </div>
          <div className="myInfo__detail">
            <p className="myInfo__detailName">
              {filteredTweets[0].username} Profile
            </p>
            <p>28 팔로워 100 팔로잉</p>
          </div>
        </div>
      </div>
      <ul className="tweets__mypage">
        {/* TODO : dummyTweets중 kimcoding 이 작성한 트윗 메세지만 있어야 합니다. */}
        <li className="tweet" id={"1"}>
          <div className="tweet__profile">
            <img src={filteredTweets[0].picture} />
          </div>
          <div className="tweet__content">
            <div className="tweet__userInfo">
              <span className="tweet__username">{filteredTweets[0].username}</span>
              <span className="tweet__createdAt">{filteredTweets[0].createdAt}</span>
            </div>
            <div className="tweet__message">{filteredTweets[0].content}</div>
          </div>
        </li>
      </ul>
      TODO : Footer 컴포넌트를 작성합니다.
      <Footer />
    </section>
  );
};

export default MyPage;

Tweets.js

import React from 'react';
import { dummyTweets } from '../static/dummyData';
import './Tweets.css';
// ! 위 코드는 수정하지 않습니다.

// TODO - import문을 이용하여 Footer 컴포넌트를 불러오세요.
import Footer from '../Footer';

const Tweets = () => {
  return (
    <div>
      <div className="tweetForm__container">
        <div className="tweetForm__wrapper">
          <div className="tweetForm__input">
            <div className="tweetForm__inputWrapper">
              <div className="tweetForm__count" role="status">
                <span className="tweetForm__count__text">
                  {'total: ' + dummyTweets.length}
                </span>
              </div>
            </div>
          </div>
        </div>
      </div>
      <ul className="tweets">
        {dummyTweets.map((tweet) => {
          return (
          <li className="tweet" id={tweet.id} key={tweet.id}>
            <div className="tweet__profile">
              <img src={tweet.picture} />
            </div>
            <div className="tweet__content">
              <div className="tweet__userInfo">
                <span className="tweet__username">{tweet.username}</span>
                <span className="tweet__createdAt">{tweet.createdAt}</span>
              </div>
              <div className="tweet__message">{tweet.content}</div>
            </div>
          </li>
          )
        })}
      </ul>
      {/* TODO - Footer 컴포넌트를 작성합니다. */}
      <Footer />
    </div>
  );
};


export default Tweets;

About.js

import React from 'react';
import './About.css';
import Footer from "../Footer"


import { dummyTweets } from "../static/dummyData";


const About = (props) => {
  const filteredTweets = dummyTweets.filter( (tweet) => {
    return tweet.username === "kimcoding";
  });
  
  return (
    <section className="aboutTwittler">
      <div className="aboutTwittler__container">
        <div className="aboutTwittler__wrapper">
          <div className="aboutTwittler__detail">
            <p className="aboutTwittler__detailName">Kimcoding Info</p>
          </div>
        </div>
      </div>
      <div className="aboutTwittler__content">
      <img src={filteredTweets[0].picture} />
      <p className="myInfo__detailName">
              {filteredTweets[0].username} Info
      </p>
      <div className="myinfo__content">
      <p className="myInfo__Job">
       Job : developer
      </p>
      <p className="myInfo__interests">
       Interests: coding , reading , playing with my Pet
      </p>
      <p className="myInfo__phoneNumber">
       PhoneNumber : 010-xxxx-xxxx
      </p>
      <p className="myInfo__capability">
      capability : HTML,CSS,JavaScript
      </p>
      </div>

      <div className="myinfo__img">
      <img src="img/coding.jpg" />
      <img src="img/reading.jpg" />
      <img src="img/dog.jpg" />
      </div>

      </div>
      <Footer />
    </section>
  );
};

export default About;

About.css

.aboutTwittler {
  display: flex;
  flex-direction: column;
  flex: 1 0 0;
}

.aboutTwittler__container {
  border-bottom: 1px solid var(--main-border-color);
  margin-bottom: 0.5rem;
}

.aboutTwittler__wrapper {
  height: 97px;
  display: flex;
  flex-direction: row;
  padding: 0.5rem 1rem;
  align-items: center;
  color : white;
  background-color: var(--about-component-color);
}

.aboutTwittler__detail {
  padding-left: 20px;
  display: flex;
  flex-direction: column;
  margin: 0.5rem;
}

.aboutTwittler__detail > .aboutTwittler__detailName {
  font-size: 1.2rem;
  font-weight: bold;
}

.aboutTwittler__content {
  flex: 1 0 80vh;
  border: 2px solid var(--about-component-color);
  overflow-y: scroll;
  display: flex;
  flex-direction: column;
  align-items: center;
}


.aboutTwittler__content > img { 
  
  margin: 30px 20px 30px 10px;
  font-size: 7rem;
  color: var(--default-text-color);
  border-radius: 30px;
}

.myInfo__detailName{
  font-size: 15px;
  padding:10px;
  background: #dad7d7;
box-shadow:  6px 6px 12px #a8a6a6,
             -6px -6px 12px #ffffff;
}



.myinfo__content {
  margin-top: 60px;
  border-radius: 5px;
  padding: 15px;
  background: #e0e0e0;
  box-shadow:  6px 6px 12px #acacac,
               -6px -6px 12px #ffffff;
   
}
.myinfo__content>p{
  font-size: 20px;
  line-height: 50px;
}


.myinfo__img>img{
  margin-top:50px;
  padding:10px;
  width: 150px;
  height:130px;
}

About.js에서  리액트 이미지 경로를 불러올때 계속 오류가 났다.

리액트에서는 컴퓨터 파일 경로를 넣어주면 동작하지 않는다.

브라우저는 샌드박스로 처리되어 디스크의 경로로 파일에 엑세스 할수 없다.

앱이 빌드 된후 서버에서 이미지가 상주할 위치의 문제라고 한다.

웹 서버가 같은 위치에 해당 파일을 가지고 있지 않아서 오류가 난다.

public에 img라는 폴더를 만들어줘서 사진을 넣어주니 쉽게 불러올 수 있다.

 

<div className="myinfo__img">
      <img src="img/coding.jpg" />
      <img src="img/reading.jpg" />
      <img src="img/dog.jpg" />
      </div>로 고쳤더니 사진이 제대로 나왔다.

 

결과

 

아이콘을 클릭할때마다 바뀐다.


Advanced

  • useNavigate 를 이용하여 뒤로가기 기능을 만들어보기
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { BrowserRouter } from 'react-router-dom';

const root =ReactDOM.render(<BrowserRouter><App/></BrowserRouter>, document.getElementById('root'));

원래 App.js에 <BrowserRouter> </BrowseRouter>가 있었지만 따로 분리해서 index.js에 넣어주었다.
브라우저 라우터 안에 적용시키지 않고 함수 밖에서 선언해서 오류가 계속 났다.
안에서 적용시키기 위해 
const root =ReactDOM.render(<App/>, document.getElementById('root')); 에서
const root =ReactDOM.render(<BrowserRouter><App/></BrowserRouter>, document.getElementById('root')); 으로
바꿔주었더니 오류가 뜨지 않았다.
 

App.js

import React from 'react';
import './App.css';
import './global-style.css';
// TODO - react-router-dom을 설치 후, import 구문을 이용하여 BrowserRouter, Routes, Route 컴포넌트를 불러오세요.
import {Routes, Route,useNavigate} from "react-router-dom";
import Sidebar from './Sidebar';
import Tweets from './Pages/Tweets';
// TODO - import문을 이용하여 MyPage, About 컴포넌트를 불러오세요.
import MyPage from './Pages/MyPage';
import About from './Pages/About';

const App = () => {
  const navigate = useNavigate();
  const goBack = () =>{
    navigate(-1);
  };
 
  const goForward = () => {
    navigate(1);
  };
 
  return (
   
    <div>
      {/* TODO - BrowserRouter 컴포넌트를 작성합니다. */}
      <button onClick={goForward}>앞으로가기</button>
      <button onClick= {goBack}>뒤로가기</button>
     
        <div className="App">
          <main>
            <Sidebar />
            <section className="features">
              <Routes>
              <Route path="/" element={<Tweets />} />
                <Route path="/about" element={<About />} />
                <Route path="/mypage" element={<MyPage />} />
              </Routes>
            </section>
          </main>
        </div>
 
    </div>
   
  );
};

// ! 아래 코드는 수정하지 않습니다.
export default App;

결과

 

 

 


예습

state -> 컴포넌트 내에서 동적으로 변할수 있는 값 => 리액트 state에 담겨져있는 값을 비교해서 변경되었을 경우 자동적으로 렌더링 해준다(깊은 복사)

props => 사이드바 컴포넌트 입장에서는 앱 컴포넌트가 부모 컴포넌트 or 상위 컴포넌트

앱 컴포넌트에 있는 state자식한테 물려주고 그것에서 해당 state사용하고 싶을때 => 사이드바 컴포넌트 입장에서는

Props형태로 전달된다.

Props => 객체

 

상위 state에서 전달된 값은 props로 넘어오고 그 props님은 객체

state와 props는 자식 관계가 형성되어있다.

props는 무조건 상위 컴포넌트에서 하위 컴포넌트로만 전달

 

'codestates > section2' 카테고리의 다른 글

React Twittler State & Props 과제  (0) 2023.01.27
Unit6 - [React] React State & Props  (0) 2023.01.26
Unit5 - [React] React SPA  (0) 2023.01.24
Unit4 - [React] Intro  (0) 2023.01.20
Unit3 - [JS/Node] 비동기  (0) 2023.01.18
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함