[Worksheet 220513] React Key, 상태 끌어올리기, Data Fetch

방예서·2022년 5월 13일
0

Worksheet

목록 보기
32/47
React 맛보기

Key와 리랜더링

    <script type="text/babel">
      const rootElement = document.getElementById("root");

      const todos = [
        { id: 1, value: "washing" },
        { id: 2, value: "running" },
        { id: 3, value: "cleaning" },
        { id: 4, value: "studying" }
      ];

      const App = () => {
        const [items, setItems] = React.useState(todos);

        const handleDoneClick = (todo) => {
          // items 에서 지금 누른 todo와 같지 않은 것만 다시 넣는다(filter)
          // 방금 누른 값만 빼고 다시 저장한다.
          setItems((items) => items.filter((item) => item !== todo));
        };

        const handleRestoreClick = () => {
          setItems((items) => [
            // todos에는 있지만(원래 있던 아이템들)
            // items(state)에는 없는 것을 다시 setItems
            // Done 눌러서 만든 items와 비교하는 것
            ...items,
            todos.find((item) => !items.includes(item))
          ]);
        };

        return (
          <>
            {items.map((todo) => (
              <div>
                <span>{todo.value}</span>
                <br />
                <button onClick={() => handleDoneClick(todo)}>Done</button>
              </div>
            ))}
            <button onClick={handleRestoreClick}>Restore</button>
          </>
        );
      };

      ReactDOM.render(<App />, rootElement);
    </script>

여기서 이런 warning이 뜬다.
unique한 key 값이 필요하다는 것.

key? value를 특정하는 이름! 우리도 지정해준 id 값이다.

Warning: Each child in a list should have a unique "key" prop.

Check the render method of `App`. See https://reactjs.org/link/warning-keys for more information.
    at div
    at App (<anonymous>:39:31)

컴포넌트들을 잘 재사용하기 위해서는 unique한 id 값을 지정해주고 사용해야한다.

unique -> 중복이 없고, 바뀌지 않는 값.

State lifting up

ID와 PW가 둘다 값이 없으면 login 버튼을 비활성화 시킬 것이다.

    <script type="text/babel">
      const rootElement = document.getElementById("root");

      const Id = () => {
        const [id, setId] = React.useState("");

        const handleIdChange = (event) => {
          setId(event.target.value);
          console.log("id" + event.target.value.length);
        };

        return (
          <>
            <label htmlFor="id">ID:</label>
            <input type="text" id="id" onChange={handleIdChange} />
          </>
        );
      };

      const Pw = () => {
        const [pw, setPw] = React.useState("");

        const handlePwChange = (event) => {
          setPw(event.target.value);
          console.log("pw" + event.target.value.length);
        };

        return (
          <>
            <label htmlFor="pw">PW:</label>
            <input type="password" id="pw" onChange={handlePwChange} />
          </>
        );
      };

      const App = () => {
        return (
          <form>
            <Id />
            <br />
            <Pw />
            <br />
            <button type="submit" disabled={true}>
              Login
            </button>
          </form>
        );
      };

      ReactDOM.render(<App />, rootElement);

이렇게 했을 때, App의 자식인 <Id /><Pw /> 의 상태를 App은 알 수 없다.
자식(Id, Pw)의 상태를 부모에게 알릴 수 있게 상태 끌어올리기가 필요하다.

    <script type="text/babel">
      const rootElement = document.getElementById("root");

      const Id = ({ handleIdChange }) => {
        return (
          <>
            <label htmlFor="id">ID:</label>
            <input type="text" id="id" onChange={handleIdChange} />
          </>
        );
      };

      const Pw = ({ handlePwChange }) => {
        return (
          <>
            <label htmlFor="pw">PW:</label>
            <input type="password" id="pw" onChange={handlePwChange} />
          </>
        );
      };

      const App = () => {
        // Id와 Pw의 상태를 App에서 알 수 있게 끌어올렸다.
        const [id, setId] = React.useState("");
        const [pw, setPw] = React.useState("");

        const handleIdChange = (event) => {
          setId(event.target.value);
          console.log("id" + event.target.value.length);
        };

        const handlePwChange = (event) => {
          setPw(event.target.value);
          console.log("pw" + event.target.value.length);
        };

        return (
          <form>
            <Id handleIdChange={handleIdChange} />
            <br />
            <Pw handlePwChange={handlePwChange} />
            <br />
            // 이제 여기서도 id와 pw의 상태를 알 수가 있게 된다.
            <button type="submit" disabled={id.length===0 || pw.length===0}>
              Login
            </button>
          </form>
        );
      };

      ReactDOM.render(<App />, rootElement);
    </script>

형제 컴포넌트의 상태가 궁금할 때, 필요하면 부모에게 lifting up 시켜서 부모도 상태를 알 수 있게 한다.
-> 하지만 과도한 lifting은 Props drilling을 야기할 수 있다.

Data fetch

  • Fetch API
    네트워크 통신 도구
React.useEffect(() => {
          fetch(
            "https://raw.githubusercontent.com/techoi/raw-data-api/main/simple-api.json"
          )
            .then((response) => response.json())
            .then((data) => console.log(data));
        }, []);

json data fetch 하기

    <script type="text/babel">
      const rootElement = document.getElementById("root");

      const App = () => {
        const [data, setData] = React.useState(null);
        const [err, setErr] = React.useState(null);

        React.useEffect(() => {
          fetch(
            "https://raw.githubusercontent.com/techoi/raw-data-api/main/simple-api.json"
          )
            .then((response) => response.json())
            .then((data) => {
              setData(data.data);
              console.log(data);
            })
          	// 에러 catch 하는 부분
            // 에러의 상태를 관리하여 에러가 발생하면 메시지를 저장한다.
            .catch((err) => {
              setErr(err.message);
            });
        }, []);

        // 에러 난 상황 핸들링
        if (err != null) {
          return <p>에러났따.</p>;
        }

        // 로딩 중 상황 핸들링
        if (data == null) {
          return <p>Loading...</p>;
        }

        return (
          <>
            <div>
              <p>People</p>
              {data.people.map((person) => (
                <div>
                  <span>name: {person.name} </span>
                  <span>age: {person.age}</span>
                </div>
              ))}
            </div>
          </>
        );
      };

      ReactDOM.render(<App />, rootElement);
    </script>
profile
console.log('bang log');

0개의 댓글