리액트 정리

꿀이·2022년 11월 14일
0

1. 컴포넌트 생성

컴포넌트를 다음과 생성하고 App.js 에서 import 해서 조각조각 모아서 사용한다.

const Home = () =>{
  return (
    <div>
      <h1>Home</h1>
      <p>이곳은 홈 입니다.</p>
    </div>
  )
}

export default Home;

2. 라우터 설정

Link 를 통해서 a태그의 ref 를 대체한다.

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

const RouteTest = ()=>{
  return (
    <>
      <Link to={"/"}>Home</Link>
      <br/>
      <Link to={"/diary"}>Diary</Link>
      <br/>
      <Link to={"/new"}>New</Link>
      <br/>
      <Link to={"/edit"}>Edit</Link>
    </>
  )
}

라우터를 사용할때 App 최상위 컴포넌트를 BrowserRouter 로 감싸주고 Routes 태그로 한번 감싸준 곳 안에다가 Route 설정을 적어준다. Routes 태그 밖에 있는것들은 항상 화면에 뿌려주는 것이다.

App 최상위 컴포넌트

Diary 부분을 보면 :id 를 통해서 pathvariable 을 넘겨주는거도 가능하다. useParams() 는 react-router 에서 제공하는 커스텀 메서드로서 객체를 리턴하는데 :id 을 구조분해할당으로 받아와서 사용할 수도 있다.

쿼리스트링을 날려야 하는 경우에는 path variable 과는 다르게 별도의 처리를 해주지 않아도 라우터가 동작한다.

function App() {
  return (
    <BrowserRouter>
      <div className="App">
        <h2>App.js</h2>
        <Routes>
          <Route path='/' element={<Home />} />    
          <Route path='/new' element={<New />} />
          <Route path='/Edit' element={<Edit />} />
          <Route path='/Diary/:id' element={<Diary />} />
        </Routes>
        <RouteTest />
      </div>
    </BrowserRouter>
  );
}

Diary 컴포넌트

import { useParams } from "react-router-dom";

const Diary = () =>{

  const {id} = useParams();
  console.log(`${id} 가 path variable 로 넘어왓습니다`);

  return (
    <div>
      <h1>diary</h1>
      <p>이곳은 일기 상세 페이지 입니다.</p>
    </div>
  )
}

export default Diary;

edit 컴포넌트

쿼리스트링의 경우 App.js 에서 따로 처리를 해줄거는 없고 ? 이후의 쿼리스트링을 알아서 파싱해 주는듯, useSearchParams() 를 통해서 파라미터들을 가져올 수 있는데, 얘는 path variable 과는 다르게 배열을 리턴함, 첫번째 배열인자의 메서드를 통해서 파라미터들을 get() 할 수 있다.

import { useSearchParams } from "react-router-dom";

const Edit = () =>{
  const [searchParams, setSearchParams] = useSearchParams();

  const id = searchParams.get("id");
  console.log("id : ", id);
  
  const mode = searchParams.get("mode");
  console.log("mode : ", mode);

  return (
    <div>
      <h1>Edit</h1>
      <p>이곳은 일기 수정 페이지 입니다.</p>
    </div>
  )
}

export default Edit;

useNavigate()

useNavigate() 를 사용하면 꼭 Link 태그를 클릭하지 않아도, 원하는 화면으로 이동시켜줄 수 있다. 예를들면 로그인 하지 않은 사용자가 특정 탭을 클릭했을때 로그인 화면으로 보내줄 수 있다.

  • navigate(-1) : 뒤로가기 기능을 하네?
import { useNavigate, useSearchParams } from "react-router-dom";

const Edit = () =>{
  const navigate = useNavigate();
  return (
    <div>
      <h1>Edit</h1>
      <p>이곳은 일기 수정 페이지 입니다.</p>
      <button onClick={()=>{
        navigate(-1);//여기다가 특정 url 을 입력하면 Link 태그를 클릭하지 않아도 된다.
      }}>뒤로가기</button>
    </div>
  )
}

export default Edit;

3. 공통 컴포넌트 처리

MyHeader 컴포넌트를 보면 props 로 MyButton 컴포넌트를 내려준걸 볼 수 있다. 이처럼 컴포넌트 자체도 props 로 내려줄 수 있는듯..!

function App() {
  return (
    <BrowserRouter>
      <div className="App">
      <MyHeader 
        headText={"App"} 
        leftChild={<MyButton text={'왼쪽 버튼'} onClick={()=>alert('왼쪽 클릭')} />}
        rightChild={<MyButton text={'오른쪽 버튼'} onClick={()=>alert('오른쪽 클릭')} />}
      />
        <h2>App.js</h2>

        {/* 공통 컴포넌트에 속하는 버튼 세개 생성 */}
        <MyButton text={'버튼'} onClick={()=>alert('버튼클릭!!')} type={'positive'}/>
        <MyButton text={'버튼'} onClick={()=>alert('버튼클릭!!')} type={'negative'}/>
        <MyButton text={'버튼'} onClick={()=>alert('버튼클릭!!')} />

MyHeader 를 한번 보면 props 로 내려온걸 바로 쓰는걸 확인할 수 있다.

const MyHeader = ({headText, leftChild, rightChild}) => {
  return (
    <header>
      <div className="head_btn_left">
        {leftChild}
      </div>
      <div className="head_text">
        {headText}
      </div>
      <div className="head_btn_right">
        {rightChild}
      </div>
    </header>
  )
}

defaultProps

MyButton 컴포넌트를 보면 .defaultProps 를 통해서 상위 컴포넌트에서 props를 안내려 줬을 때의 default 값을 설정해줄 수 있다.

const MyButton = ({text,type,onClick})=>{
  return(
    <button className={["MyButton",`MyButton_${type}`].join(' ')} onClick={onClick} >
      {text}
    </button>
  )
}

MyButton.defaultProps = {
  type: "default",
}

4. 상태 관리 : useReducer

상태의 개수가 많아지면 중복코드가 길어지고 유지보수를 어렵게 만든다. 그래서 등장한게 useReducer 이고 다음과 같이 사용한다.

dispatch를 호출할때 매겨변수로 넘어가는 객체를 Action 객체 라고 한다. 얘는 어떤 액션인지 구분하는 type 을 반드시 가지고 있어야 한다.

이 객체가 reducer 메서드 로 날아가게 된다. reducer는 넘어온 action 객체 내부의 type 을 보고 어떻게 상태를 변화시킬지 결정한다.

const [state,dispatch(상태변화 유발 함수)] = useReducer(reducer(일어난 상태변화를 처리하는 함수),"초기값")

//버튼 클릭 이벤트
<button onClick={()=> dispatch({
  type:1, // 이건 반드시 있어야 한다.
  데이터:불라불라
})}>버튼</button>

//reducer 메서드
const reducer = (state,action) => {
  switch(action.type){
    case 1:
      return state + 1;
    case 2:
      return state + 10;
  }
  
}

5. Context : 컴포넌트 트리에 데이터 공급

최상위 App 에서 하위 컴포넌트들에게 props 를 내려줄때 단순히 중간 경유지의 컴포넌트들이 존재하게 된다. 근데 이렇게 하다보면 유지보수시에 어려움이 따른다. (요런걸 props 드릴링) 이라고 한다.

요런 문제를 해결하기 위해 나온게 Context 다. 최상위 App 컴포넌트 아래에 provider 라는 중간 컴포넌트가 있고, 요게 하위에 있는 여러 컴포넌트들에게 props를 직접 내려줄 수 있다.

props 를 공유할 컴포넌트들을 Provider 컴포넌트로 감싸주고 공유할 props 들을 value={.., .., ..} 로 공유할 수 있다. 근데 이때 Event 콜백 함수들은 따로 내려주는걸 알 수 있는데, Provider 도 컴포넌트기 때문에 변경이 일어나면 렌더링이 다시 일어나게 된다. 그래서 상황에 따라서 context 를 분리를 해줘야 한다.

useMemo() 로 애써 감싸준거를 풀리지 않도록 신경써야 하는듯

여러개를 내려줄 때는 받는쪽에서 구조분해 할당으로 가져와서 사용할 수 있다.


export const DiaryStateContext = React.createContext();
export const DiaryDispatchContext = React.createContext();

  return (
    <DiaryStateContext.Provider value = {data}>
      <DiaryDispatchContext.Provider value={{onCreate,onEdit,onRemove}}>
        <BrowserRouter>
          <div className="App">
            <Routes>
              <Route path='/' element={<Home />} />    
              <Route path='/new' element={<New />} />
              <Route path='/Edit' element={<Edit />} />
              <Route path='/Diary/:id' element={<Diary />} />
            </Routes>
          </div>
        </BrowserRouter>
      </DiaryDispatchContext.Provider>
    </DiaryStateContext.Provider>
  );

props 내려 받는쪽에서는 다음과 같이 받을 수 있다.

const Home = () =>{
  const diaryList = useContext(DiaryStateContext);
profile
내게 맞는 옷을 찾는중🔎

0개의 댓글