2 분 소요

1. Additional Hooks

  • useReducer
    • 다수의 하위값을 포함하는 복잡한 정적 로직을 만드는 경우
    • 다음 state가 이전 state에 의존적인 경우
    • Redux를 안다면 쉽게 사용 가능
// src/components/Example6.jsx

// reducer => state를 변경하는 로직이 담겨 있는 함수
const reducer = (state, action) => {
  if (action.type === "PLUS") {
    return {
      count: state.count + 1,
    };
  }
  return state;
};

// dispatch => action 객체를 넣어서 실행

// action => 객체이고 필수 프로퍼티로 type을 가짐

export default function Example6() {
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  return (
    <div>
      <p>You clicked {state.count} times</p>
      <button onClick={click}>Click me</button>
    </div>
  );

  function click() {
    dispatch({ type: "PLUS" });
  }
}


// src/App.js

import logo from "./logo.svg";
import "./App.css";
import Example6 from "./components/Example6";
import useWindowWidth from "./hooks/useWindowWidth";
import withHasMounted from "./hocs/withHasMounted";
import useHasMounted from "./hooks/useHasMounted";

function App({ hasMounted }) {
  const width = useWindowWidth();
  const hasMountedFromHooks = useHasMounted();

  console.log(hasMounted, hasMountedFromHooks);

  return (
    <div className="App">
      <header className="header">
        <img src={logo} className="logo" alt="logo" />
        <Example6 />
        {width}
      </header>
    </div>
  );
}

export default withHasMounted(App);


react-hook9


// src/components/Example7.jsx

import { useState, useMemo } from "react";

function sum(persons) {
  console.log("sum...");
  return persons.map((person) => person.age).reduce((l, r) => l + r, 0);
}

export default function Example7() {
  const [value, setValue] = useState("");
  const [persons] = useState([
    { name: "LWW", age: 29 },
    { name: "Amy", age: 38 },
  ]);

  const count = useMemo(() => {
    return sum(persons);
  }, [persons]);

  const click = useCallback(() => {
    console.log(value);
  });

  return (
    <div>
      <input value={value} onChange={change} />
      <p>{count}</p>
      <button onClick={click}>click</button>
    </div>
  );

  function change(e) {
    setValue(e.target.value);
  }
}


// src/App.js

import logo from "./logo.svg";
import "./App.css";
import Example7 from "./components/Example7";
import useWindowWidth from "./hooks/useWindowWidth";
import withHasMounted from "./hocs/withHasMounted";
import useHasMounted from "./hooks/useHasMounted";

function App({ hasMounted }) {
  const width = useWindowWidth();
  const hasMountedFromHooks = useHasMounted();

  console.log(hasMounted, hasMountedFromHooks);

  return (
    <div className="App">
      <header className="header">
        <img src={logo} className="logo" alt="logo" />
        <Example7 />
        {width}
      </header>
    </div>
  );
}

export default withHasMounted(App);


react-hook10


// src/components/Example8.jsx

import { useState } from "react";

export default function Example8() {
  const [value, setValue] = useState("");
  const input1Ref = createRef();
  const input2Ref = useRef();

  console.log(input1Ref.current, input2Ref.current);

  return (
    <div>
      <input value={value} onChange={change} />
      <input ref={input1Ref} />
      <input ref={input2Ref} />
    </div>
  );

  function change(e) {
    setValue(e.target.value);
  }
}


// src/App.js

import logo from "./logo.svg";
import "./App.css";
import Example7 from "./components/Example8";
import useWindowWidth from "./hooks/useWindowWidth";
import withHasMounted from "./hocs/withHasMounted";
import useHasMounted from "./hooks/useHasMounted";

function App({ hasMounted }) {
  const width = useWindowWidth();
  const hasMountedFromHooks = useHasMounted();

  console.log(hasMounted, hasMountedFromHooks);

  return (
    <div className="App">
      <header className="header">
        <img src={logo} className="logo" alt="logo" />
        <Example8 />
        {width}
      </header>
    </div>
  );
}

export default withHasMounted(App);


react-hook11


2. React Router Hooks

// src/components/LoginButton.jsx

import { useHistory, withRouter } from "react-router-dom";

export default function LoginButton() {
  const history = useHistory();
  function login() {
    setTimeout(() => {
      history.push("/");
    }, 1000);
  }

  return <button onClick={login}>로그인하기</button>;
});


react-router11

react-router12


// src/pages/Profile.jsx

export default function Profile() {
  const params = useParams();
  const id = params.id;
  console.log(id, typeof id);
  return (
    <div>
      <h2>Profile 페이지</h2>
      {id && <p>id는 {id}입니다.</p>}
    </div>
  );
}


react-router10

댓글남기기