React props,useState 직접 설정해보기

돌리의 하루·2023년 1월 26일
0
post-thumbnail

요 근래 react를 계속 열심히 익히는중이다😎
잠자는 시간이 아까운게 이런 기분일까😔 후후...

아무튼 각설하고, react에서 가장 헷갈리는 점은 아무래도 props랑 useState가 아닐까 싶다.
두 요소의 개념적인 차이점은,

  • state : 변할 수 있는 값, 유동적 , 컴포넌트 사용 중 내부에서 변할 수 있는 값
  • props : 외부로부터 전달받은 값, 함부로 변경될 수 없는 읽기전용객체

react에서는 props,useState사용이 빈번한만큼, 중요한 개념이 아닐수없다.

밑의 코드들은 트위터의 내용을 간단하게 구현해본건데, 작성자가 적은 form을 트윗에 포함시켜서 내보내는 기능을 구현했다.

이번 과제의 코드를 예로 들어 내가 알게된 점을 쭉 적으며 상기시켜봐야겠다.
❌코드 안에 있는 //숫자는 무시해주세요! 설명을 덧붙이려고 코드에 직접 삽입한 숫자입니다.

//App.js
import React from 'react';
import {BrowserRouter, Routes, Route} from 'react-router-dom';//1

import Sidebar from './Sidebar';
import Tweets from './Pages/Tweets';
import About from './Pages/About';
//2
import './App.css';
import './global-style.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>
        </section>
      </main>
    </div>
    </BrowserRouter>
  );
};

export default App;
  • //1 : react에 필요한 {BrowserRouter, Routes, Route}을 import
  • //2 : 각각의 컴포넌트들을 import로 가져와서 Routes 안에 Route로 불러오고 있다.
//Tweet.js
import React from 'react';
import './Tweet.css';

const Tweet = ({ tweet }) => { //1
  const parsedDate = new Date(tweet.createdAt).toLocaleDateString('ko-kr');

  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">
            <span className='tweet__username'>{tweet.username}</span>
            <span className='tweet__createdAt'>{parsedDate}</span>
          </div>
        </div>
        <div className="tweet__message">
          {tweet.content}
        </div>
      </div>
    </li>
  );
};

export default Tweet;
  • 위의 코드는 트윗의 형식을 나타내고 있다. Tweet을 default하고 다른 컴포넌트에서 prop으로 사용할 수 있는 구조다.
    const Tweet = ({ tweet }) 부분을 자세히 살펴보면, 다른 컴포넌트에서
    Ex) <Tweet tweet={something} /> 와 같이 사용가능하다.
//Tweet.js
import React, { useState } from 'react';
import Footer from '../Footer';
import Tweet from '../Components/Tweet';
import './Tweets.css';
import dummyTweets from '../static/dummyData';

const Tweets = () => {
  const [tweets, setTweets] = useState(dummyTweets) //1
  const [username, setUsername] = useState("");
  const [msg, setMsg] = useState("");
  const getRandomNumber = (min, max) => {
    return parseInt(Math.random() * (Number(max) - Number(min) + 2));
  };

  const handleButtonClick = (event) => {
    const tweet = {//2
      id: tweets.length + 1,
      username: username,
      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'),
    };

    console.log([tweets])
    console.log([tweet,...tweets])  //그냥 tweet로 쓰면  배열, 객체, 문자열의 요소를 모두 꺼내준게 아닌 그냥 Array로 나온다.
    setTweets([tweet,...tweets]) //이거 배열로 나오는거 맞음 []안에 객체 6개있는걸로 나옴//3
    
   
    //dummydata + 전송된 트윗 = tweets
  };

  const handleChangeUser = (event) => {
    setUsername(event.target.value)
  };

  const handleChangeMsg = (event) => {
    setMsg(event.target.value)
  };

  return (
    <React.Fragment>
      <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"
                  placeholder="your username here.."
                  className="tweetForm__input--username"
                  onChange={handleChangeUser}
                  value={username}
                ></input>

                <textarea
                  placeholder="write here.."
                  className="tweetForm__input--message"
                    onChange={handleChangeMsg}
                      value={msg}
                      >
                </textarea>
                
              </div>
              <div className="tweetForm__count" role="status">
                <span className="tweetForm__count__text">
                  {'total:'+ tweets.length}
                </span>
              </div>
            </div>
            <div className="tweetForm__submit">
              <div className="tweetForm__submitIcon"></div>
           
              <button className='tweetForm__submitButton' onClick={handleButtonClick}>submit</button>
            </div>
          </div>
        </div>
      </div>
      <div className="tweet__selectUser"></div>
      <ul className="tweets">
        
        {tweets.map((value) => <Tweet key={value.id} tweet={value} />)}//4

      </ul>
      <Footer />
    </React.Fragment>
  );
};

export default Tweets;
  • //1 : usestate로 설정해준 모습이다. tweets을 dummy~로 설정하고,
    useState 초깃값은 dummy~로 설정해줬다.
    그 밑으로는 각각 input과 textare를 change하는 이벤트를 저장하는 useState를 만들었다.

  • //2 : submit 버튼을 누르게 되면, 일어나는 event를 정리해놓은 곳이다. const tweet으로 객체를 직접 설정해서, 폼에 작성하는 작성자의 id 등등을 useState변수로 설정한다. 폼을 보여주는 곳은 밑에서 따로 작성한다.

  • //3 : 위의 useState변수들을 잘 기억해야한다. tweets는 dummydata(더미데이터)라서 데이터들을 받아오는 곳이라고 생각하면 된다.
    그리고 직접 설정한 변수 tweet을 합쳐서 트윗을 보여줘야 하기 때문에 tweets에 둘을 합치는 함수 setTweets를 작성해줘야 한다. tweets를 그대로 쓰면 배열이 직접 리턴되기 때문에, 여기서는 spread연산자를 써줘야한다. 따라서 작성자가 쓴 폼 + 기존 데이터를 [작성자가쓴 form + ...dummydata]형식의 함수로 받아준 후 tweets에 리렌더링하게 된다.

  • //4 : Tweet의 prop을 받아와서 map으로 새로운 함수로 만든다. 여기서 prop으로 tweet이 사용되고, map의 인자가 tweet안의 데이터로 들어가서 그려낸다.

profile
진화중인 돌리입니다 :>

0개의 댓글