2020.코딩일지
React실습 - react-twittler-state-props 본문
728x90
Sprint - React Twittler state-props
깃헙에서 fork - 내 로컬로 clone
npm install
.json을 보니, 응? 이미 "react-router-dom": "^6.3.0", 설치되어있습니다?!
( 생략 )npm install react-router-dom
(npm t) npm run test
npm run start
npm run submit
myPage.js Tweets.js
App.js
import React from 'react'; // 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 : MyPage, About 컴포넌트를 import 합니다. import Mypage from './Pages/MyPage'; import About from './Pages/About' import './App.css'; const App = (props) => { return ( <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> {/* TODO : 유어클래스를 참고해서, 테스트 케이스를 통과하세요. TODO : React Router DOM 설치 후 BrowserRouter, Routes, Route의 주석을 해제하고 Routes, Route 컴포넌트를 적절하게 작성합니다. */} {/* Route 예시: <Route path="/" element={<Tweets />}></Route> */} </section> </main> </div> </BrowserRouter> ); }; // ! 아래 코드는 수정하지 않습니다. export default App;
index.js
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import dummyTweets from './static/dummyData'; ReactDOM.render( <App dummyTweets={dummyTweets} />, document.getElementById('root') );
Sidebar.js
import React from 'react'; // TODO : React Router DOM의 Link 컴포넌트를 import 합니다. import { Link } from 'react-router-dom'; const Sidebar = () => { return ( <section className="sidebar"> {/* TODO : Link 컴포넌트를 작성하고, to 속성을 이용하여 경로(path)를 연결합니다. */} <Link to="/"><i className="far fa-comment-dots"></i></Link> <Link to="/about"><i className="far fa-question-circle"></i></Link> <Link to="/mypage"><i className="far fa-user"></i></Link> </section> ); }; export default Sidebar;
Footer.js
import React from 'react'; const Footer = () => { return <div> <footer> copyright from EG220718 </footer> </div>; }; // TODO : Footer 함수 컴포넌트를 작성합니다. 시멘틱 요소 footer가 포함되어야 합니다. // 🥺대문자 쓰면 무한루프 돌면서 heap out of memory 에러 발생 // 아마도 'Footer가 Footer를 그러니까 Footer가 Footer를 아니그래서 Footer가 Footer를 그랬다니까'무한반복st.이여서 그러지 않았나 생각해봅니🙃 export default Footer;
pages/Tweets.js -- ver1.페어님것참고
// TODO : useState를 react로 부터 import 합니다. import React, { useState} from 'react'; import Footer from '../Footer'; import Tweet from '../Components/Tweet'; import './Tweets.css'; import dummyTweets from '../static/dummyData'; const Tweets = () => { // TODO : 새로 트윗을 작성하고 전송할 수 있게 useState를 적절히 활용하세요. const [name, setName] = useState(''); const [message, setMessage] = useState(''); const [list, setList] = useState([]); const handleButtonClick = (event) => { const tweet = { id: '0', username: name, picture: 'https://randomuser.me/api/portraits/men/98.jpg', content: message, createdAt: new Date(), updatedAt: new Date() }; // TODO : Tweet button 엘리먼트 클릭시 작동하는 함수를 완성하세요. // 트윗 전송이 가능하게 작성해야 합니다. setList([tweet, ...list]); }; const handleChangeUser = (event) => { // TODO : Tweet input 엘리먼트에 입력 시 작동하는 함수를 완성하세요. setName(event); }; const handleChangeMsg = (event) => { // TODO : Tweet textarea 엘리먼트에 입력 시 작동하는 함수를 완성하세요. setMessage(event); }; return ( <React.Fragment> <div className="tweetFormcontainer"> <div className="tweetFormwrapper"> <div className="tweetFormprofile"> <img src="https://randomuser.me/api/portraits/men/98.jpg" /> </div> <div className="tweetForminputContainer"> <div className="tweetForminputWrapper"> <div className="tweetForminput"> <input onChange={(e)=>handleChangeUser(e.target.value)} type="text" defaultValue="parkhacker" placeholder="your username here.." className="tweetForm__input--username" ></input> <textarea className="tweetForm__input--message" onChange={(e)=>handleChangeMsg(e.target.value)}></textarea> </div> <div className="tweetFormcount" role="status"> <span className="tweetFormcounttext"> {/* TODO : 트윗 총 개수를 보여줄 수 있는 Counter를 작성하세요. */} {`total: ${dummyTweets.length}`} </span> </div> </div> <div className="tweetFormsubmit"> <button className="tweetForm__submitButton" onClick={()=>handleButtonClick()}> <div className="tweetFormsubmitIcon">Tweet</div> </button> </div> </div> </div> </div> <div className="tweet__selectUser"></div> <ul className="tweets"> {list.map((data, index) =>( <Tweet key={index} tweet={data}/> ))} {dummyTweets.map((data, index)=>( <Tweet key={index} tweet={data} /> ))} </ul> <Footer /> </React.Fragment> ); }; export default Tweets;
pages/Tweets.js --ver2.선배님것참고
// TODO : useState를 react로 부터 import 합니다. import React, { useState } from 'react'; import Footer from '../Footer'; import Tweet from '../Components/Tweet'; import './Tweets.css'; import dummyTweets from '../static/dummyData'; const Tweets = () => { // TODO : 새로 트윗을 작성하고 전송할 수 있게 useState를 적절히 활용하세요. const getRandomNumber = (min, max) => { return parseInt(Math.random() * (Number(max) - Number(min) + 2)); }; const [user, setUser] = useState('parkhacker'); const [msg, setMsg] = useState(''); const [tweets, setTweets] = useState(dummyTweets); const handleButtonClick = (event) => { const tweet = { id: dummyTweets.length+1, username: user, picture: `https://randomuser.me/api/portraits/women/${getRandomNumber( 1, 98 )}.jpg`, content :msg, createdAt : new Date().toLocaleDateString('ko-kr'), updatedAt : new Date().toLocaleDateString('ko-kr'), }; // TODO : Tweet button 엘리먼트 클릭시 작동하는 함수를 완성하세요. // 트윗 전송이 가능하게 작성해야 합니다. setTweets([tweet, ...tweets]) }; const handleChangeUser = (event) => { setUser(event.target.value) // TODO : Tweet input 엘리먼트에 입력 시 작동하는 함수를 완성하세요. }; const handleChangeMsg = (event) => { setMsg(event.target.value) // TODO : Tweet textarea 엘리먼트에 입력 시 작동하는 함수를 완성하세요. }; return ( <React.Fragment> {/* Fragment는 DOM에 별도의 노드를 추가하지 않고 여러 자식을 그룹화 할 수 있다. https://ko.reactjs.org/docs/fragments.html */} <div className="tweetForm__container"> <div className="tweetForm__wrapper"> <div className="tweetForm__profile"> <img src="https://randomuser.me/api/portraits/men/98.jpg" /> </div> <div className="tweetForm__inputContainer"> <div className="tweetForm__inputWrapper"> <div className="tweetForm__input"> <input type="text" defaultValue="parkhacker" value={user} //여기추가 placeholder="your username here.." className="tweetForm__input--username" onChange={handleChangeUser} ></input> {/* TODO : 트윗을 작성할 수 있는 textarea 엘리먼트를 작성하세요. */} <textarea defaultValue={""} placeholder="your message here.." className="tweetForm__input--message" onChange={handleChangeMsg} value={msg} ></textarea></div> <div className="tweetForm__count" role="status"> <span className="tweetForm__count__text"> {/* TODO : 트윗 총 개수를 보여줄 수 있는 Counter를 작성하세요. */} {'total: '+ tweets.length} </span> </div> </div> <div className="tweetForm__submit"> <div className="tweetForm__submitIcon"></div> {/* TODO : 작성한 트윗을 전송할 수 있는 button 엘리먼트를 작성하세요. */} <button className="tweetForm__submitButton" onClick={handleButtonClick}>Tweet</button> </div> </div> </div> </div> <div className="tweet__selectUser"></div> <ul className="tweets"> {/* TODO : 하나의 트윗이 아니라, 주어진 트윗 목록(dummyTweets) 갯수에 맞게 보여줘야 합니다. */} {/* <Tweet tweet={dummyTweets[0]} /> */} {tweets.map((el) => { return ( <Tweet tweet={el} /> )})} </ul> <Footer /> </React.Fragment> ); }; export default Tweets;
pages/MyPage.js
import React from 'react'; import Footer from '../Footer'; import Tweet from '../Components/Tweet'; import './MyPage.css'; import dummyTweets from '../static/dummyData'; const MyPage = () => { // const filteredTweets = dummyTweets; // TODO : 주어진 트윗 목록(dummyTweets)중 현재 유져인 parkhacker의 트윗만 보여줘야 합니다. const filteredTweets = dummyTweets.filter((tweet) => { return tweet.username === 'parkhacker'; }) return ( <section className="myInfo"> <div className="myInfo__container"> <div className="myInfo__wrapper"> <div className="myInfo__profile"> <img src={filteredTweets[0].picture} /> {/*[1]을 [0]으로 수정 */} </div> <div className="myInfo__detail"> <p className="myInfo__detailName"> {filteredTweets[0].username} Profile {/*[1]을 [0]으로 수정 */} </p> <p>28 팔로워 100 팔로잉</p> </div> </div> </div> <ul className="tweets__mypage"> <Tweet tweet={filteredTweets[0]}/> {/* TODO : 주어진 트윗 목록(dummyTweets)중 현재 유져인 parkhacker의 트윗만 보여줘야 합니다. */} {/* 또는 아래처럼. parkhacker의 tweet갯수가 0개이상일 때, map함수가 실행되게끔 할수도 있다. */} {/* {filteredTweets.length > 0 && filteredTweets.map((filteredTweet, index) => <Tweet key={index} tweet={filteredTweet} setTweet={props.setLoadedTweets} allTweet={props.loadedTweets}/>)} */} </ul> <Footer /> </section> ); }; export default MyPage;
pages/About.js (bare minimum이라 수정한건 없음)
import React from 'react'; import Footer from '../Footer'; import './About.css'; const About = (props) => { return ( <section className="aboutTwittler"> <div className="aboutTwittler__container"> <div className="aboutTwittler__wrapper"> <div className="aboutTwittler__detail"> <p className="aboutTwittler__detailName">React Twittler Info</p> </div> </div> </div> <div className="aboutTwittler__content"> <i className="fas fa-users"></i> <p>나만의 Twittler 소개페이지를 꾸며보세요.</p> </div> <Footer /> </section> ); }; export default About;
components/Tweet.js
import React from 'react'; import './Tweet.css'; const Tweet = ({ tweet }) => { const parsedDate = new Date(tweet.createdAt).toLocaleDateString('ko-kr'); // const parsedDate = new Date(tweet.createdAt).toLocaleDateString(); //이것도가능 return ( <li className="tweet" id={tweet.id}> <div className="tweet__profile"> <img src={tweet.picture} /> </div> <div className="tweet__content"> <div className="tweet__userInfo"> <div className="tweet__userInfo--wrapper"> {/* TODO : 유져 이름이 있어야 합니다. */} {/* TODO : 트윗 생성 일자가 있어야 합니다. parsedDate를 이용하세요. */} <span className="tweet__username">{tweet.username}</span> <span className="tweet__createdAt">{parsedDate}</span> </div> </div> <div className="tweet__message"> {/* TODO : 트윗 메세지가 있어야 합니다. */} {tweet.content} </div> </div> </li> ); }; export default Tweet;
'JS & React' 카테고리의 다른 글
[!!js]자바스크립트JavaScript 느낌표두개 연산자Operator (0) | 2022.07.24 |
---|---|
[에러해결]Module not found: Error: Can't resolve './reportWebVitals' (0) | 2022.07.23 |
[React] 기초2- React 데이터 흐름 [BEB 6th]009일차 (0) | 2022.07.17 |
React 실습 - Controlled Component (0) | 2022.07.16 |
React 실습 - React Event handling (0) | 2022.07.16 |
Comments