5개 핵심 과정 반응 강좌 가르치지 않음

개발자가 알아야 할 많은 기본 개념과 과정은 대부분의 강좌에서 언급되지 않았다.
나는 이미 내가 너희들에게 가장 중요하다고 생각하는 몇 가지 화제를 정성껏 골랐지만, 전문적으로 시간을 들여 상세하게 소개하는 문장은 매우 드물다.
다른 곳에서 찾을 수 없을 수도 있는 다섯 가지 이해할 만한 관건적인 과정을 살펴보자.

Want to learn all the skills you need to become a highly-paid React developer? Check out the React Bootcamp.


1. React 상태를 실제로 업데이트하는 방법


React 개발자로서 useStateuseReducer 갈고리를 사용하여 창설과 업데이트 상태를 알 수 있습니다.
그러나 이 갈고리 중 어떤 것을 사용해서 구성 요소를 업데이트할 때 어떤 일이 일어날까요?상태가 지금 업데이트됩니까 아니면 나중에 업데이트됩니까?
아래의 코드를 봅시다. 이것은 매우 간단한 계수기 응용 프로그램입니다.예상대로 버튼을 누르면 카운터가 1 증가합니다.
import React from 'react';

export default function App() {
  const [count, setCount] = React.useState(0)

  function addOne() {
    setCount(count + 1);
  }

  return (
    <div>
      <h1>Count: {count}</h1> {/* 1 (as we expect) */}

      <button onClick={addOne}>+ 1</button>
    </div>
  );
}
그러나 만약 우리가 한 줄을 추가하려고 시도한다면, 이것도 우리의 계수 1을 업데이트할 것이다.너는 무슨 일이 발생할 것이라고 생각하니?
당신이 버튼을 눌렀을 때, 우리가 표시하는 계수는 하나 증가합니까? 아니면 두 개 증가합니까?
import React from 'react';

export default function App() {
  const [count, setCount] = React.useState(0)

  function addOne() {
    setCount(count + 1);
    setCount(count + 1);
  }

  return (
    <div>
      <h1>Count: {count}</h1> {/* 1?! */}

      <button onClick={addOne}>+ 1</button>
    </div>
  );
}
만약 우리가 이 코드를 운행한다면, 우리는 그것이 단지 하나만 증가한 것을 볼 수 있을 것이다.계수를 두 번 늘리려고 시도했지만, 두 번의 단독 상태 업데이트가 있었다.
왜 우리의 계수기는 1을 표시하는데, 비록 상태가 뚜렷하게 2배 증가했지만?
이것은 React가 우리가 처음으로 상태를 업데이트할 때 호출할 때 상태 업데이트를 실행할 계획이기 때문이다.그것은 계획된 것일 뿐이고, 즉각 실행되지 않기 때문에 (이것은 비동기적이며, 동기화된 것이 아니기 때문에) 두 번째 업데이트를 시도하기 전에, 우리의 count 변수는 업데이트되지 않을 것이다.
다시 말하면 상태 갱신은 계획된 것이지 즉각 집행되는 것이 아니기 때문에 우리는 두 번째로 setCount, count을 호출했지만 여전히 0이 아니라 1에 불과했다.
비록 상태 업데이트는 비동기적이지만, 우리는 useState setter 함수에서 사용할 수 있는 내부 함수를 사용하여 이 문제를 복구하여 신뢰할 수 있게 상태를 업데이트할 수 있다.
이것은 이전 상태를 가져오고 내부 함수체에 있는 값을 되돌려줍니다.우리가 이 모드를 사용할 때, 우리는 그것이 우리가 처음에 원했던 것처럼 두 배로 증가한 것을 보았다.
import React from 'react';

export default function App() {
  const [count, setCount] = React.useState(0)

  function addOne() {
    setCount(prevCount => prevCount + 1); // 1
    setCount(prevCount => prevCount + 1); // 2
  }

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={addOne}>+ 1</button>
    </div>
  );
}

2. 단일 효과 대신 다양한 효과 사용


부작용을 수행할 때 대부분의 React 개발자들은 useEffect을 한 번만 실행하고 같은 효과 함수에서 여러 부작용을 수행하려고 시도한다.
그것은 어떤 모양입니까?다음은useEffect 갈고리에서 댓글과 댓글 데이터를 얻은 위치를 보고 각각의 상태 변수에 넣을 수 있습니다.
import React from "react";

export default function App() {
  const [posts, setPosts] = React.useState([]);
  const [comments, setComments] = React.useState([]);

  React.useEffect(() => {
    // fetching post data
    fetch("https://jsonplaceholder.typicode.com/posts")
      .then((res) => res.json())
      .then((data) => setPosts(data));

    // fetching comments data
    fetch("https://jsonplaceholder.typicode.com/comments")
      .then((res) => res.json())
      .then((data) => setComments(data));
  }, []);

  return (
    <div>
      <PostsList posts={posts} />
      <CommentsList comments={comments} />
    </div>
  );
}
모든 부작용을 효과 연결에 넣으려는 시도와는 달리 상태 연결을 여러 번 사용할 수 있는 것처럼 여러 효과를 사용할 수 있다.
이렇게 하면 우리는 서로 다른 행동을 서로 다른 효과로 나누어 관심사를 더욱 잘 분리할 수 있다.
클래스 구성 요소에서 생명주기 방법을 사용하는 것보다 React 갈고리가 제공하는 주요한 장점은 관심사를 더욱 잘 분리하는 것이다.예를 들어 componentDidMount과 같은 방법에는 구성 요소를 설치한 후에 우리가 실행하고자 하는 모든 조작이 포함되어 있어야 한다.너는 부작용을 여러 가지 방법으로 분해할 수 없다.클래스의 각 라이프 사이클 방법은 한 번만 사용할 수 있습니다.
React 갈고리의 주요 장점은 우리가 코드가 하는 일에 따라 코드를 분해할 수 있다는 것이다.렌더링된 후 수행된 작업을 여러 효과로 분리할 수 있을 뿐만 아니라 상태를 함께 배치할 수도 있습니다.
import React from "react";

export default function App() {
  const [posts, setPosts] = React.useState([]);
  React.useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/posts")
      .then((res) => res.json())
      .then((data) => setPosts(data));
  }, []);

  const [comments, setComments] = React.useState([]);
  React.useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/comments")
      .then((res) => res.json())
      .then((data) => setComments(data));
  }, []);

  return (
    <div>
      <PostsList posts={posts} />
      <CommentsList comments={comments} />
    </div>
  );
}
이것은 우리가 상태 갈고리와 이와 관련된 효과 갈고리를 함께 놓을 수 있다는 것을 의미한다. 이것은 우리의 코드를 더욱 잘 조직하고 그것이 무엇을 하는지 한눈에 이해하는 데 도움이 된다.

3. 업데이트 상태의 함수를 최적화하지 마십시오(useState,useReducer)


부모 어셈블리에서 서브어셈블리로 콜백 함수를 전달할 때 매개변수가 변경되지 않는 한 일반적으로 재생성되지 않도록 해야 합니다.
우리는 useCallback 갈고리의 도움을 받아 최적화할 수 있다.
하위 구성 요소에 전달되는 리셋 함수를 위해 만들어진 것입니다. 불필요하게 리셋되지 않도록 하기 위해서, 리셋할 때 구성 요소에 성능에 영향을 줍니다.
부모 어셈블리가 다시 렌더링될 때마다 모든 서브어셈블리가 다시 렌더링됩니다.이것이 바로 다시 렌더링할 때마다 리셋 함수를 다시 만드는 이유입니다.
단, setter 함수를 사용하면useState나useReducer 갈고리로 만든 상태를 업데이트합니다.우리는useCallback으로 그것을 포장할 필요가 없다.
다시 말하면 이렇게 할 필요가 없다.
import React from "react";

export default function App() {
  const [text, setText] = React.useState("")

  // Don't wrap setText in useCallback (it won't change as is)
  const handleSetText = React.useCallback((event) => {
    setText(event.target.value);
  }, [])

  return (
    <form>
      <Input text={text} handleSetText={handleSetText} />
      <button type="submit">Submit</button>
    </form>
  );
}

function Input({ text, handleSetText }) {
  return(
    <input type="text" value={text} onChange={handleSetText}  />
  )
}
원인은 React 문서에서 직접 발생합니다.

React guarantees that setState function identity is stable and won't change on re-renders. This is why it's safe to omit from the useEffect or useCallback dependency list.


따라서, 우리는useCallback을 사용하여 불필요한 최적화를 할 필요가 없을 뿐만 아니라, 이것을useEffect에 의존항으로 포함할 필요도 없다. 왜냐하면 이것은 변하지 않기 때문이다.
이 점은 매우 중요하다. 많은 상황에서 우리가 사용해야 할 코드를 줄일 수 있기 때문이다. 가장 중요한 것은 코드를 최적화하는 것은 헛된 시도이다. 왜냐하면 그 자체가 성능 문제를 일으킬 수 있기 때문이다.

4.useRef 갈고리는 렌더링에 걸쳐 상태를 보존할 수 있습니다


React 개발자로서, 때로는ref의 도움으로 주어진React 요소를 인용할 수 있어 매우 유용하다. 우리는 React에서 useRef 갈고리를 통해ref를 만든다.
그러나 주의해야 할 것은use ref가 특정한 DOM 요소를 인용하는 데 도움이 되는 것은 아니다.React 파일 자체는 이렇게 말합니다.

The ref object that's created by useRef is a generic container with a current property that's mutable and can hold any value.


useRef 저장소와 업데이트 값을 사용하면 어느 정도 장점이 있습니다.메모리에 저장되지 않는 값을 저장할 수 있기 때문에 다시 렌더링할 때 지워지지 않습니다.
단순 변수의 도움말 아래 렌더링 과정에서 값을 추적하려면, 구성 요소가 렌더링될 때마다 다시 초기화됩니다.단,ref를 사용하면, 그 안에 저장된 값은 구성 요소의 렌더링에서 변하지 않습니다.
이런 식으로useref를 이용하는 용례는 무엇입니까?
초기 렌더링 시 지정된 부작용만 수행하려는 경우 다음과 같은 도움이 될 수 있습니다.
import React from "react";

export default function App() {
  const [count, setCount] = React.useState(0);
  const ref = React.useRef({ hasRendered: false });

  React.useEffect(() => {
    if (!ref.current.hasRendered) {
      ref.current.hasRendered = true;
      console.log("perform action only once!");
    }
  }, []);

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Count: {count}</button>
    </div>
  );
}
이 코드를 스스로 실행해 보세요.
보시다시피 버튼을 몇 번 눌러도 상태가 업데이트되고 다시 렌더링됩니다. 우리가 실행하고자 하는 작업은 (console.log 참조) 한 번만 실행됩니다.

5. React 애플리케이션의 충돌을 방지하는 방법


React 개발자가 알아야 할 가장 중요한 경험 중 하나는 포획되지 않은 오류를 어떻게 처리하는지, 특히 그들이 React 프로그램을 웹으로 전송하지 않았다면.
다음 예시에서, 우리는 프로그램에 제목 구성 요소를 표시하려고 했지만, 실행하는 동작이 오류를 초래할 수 있습니다.즉, 빈 값에서 속성을 가져오려고 합니다.
import React from "react";

export default function App() {
  return (
    <>
      <Header />
    </>
  );
}

function Header() {
  const user = null;

  return <h1>Hello {user.name}</h1>; // error!
}
만약 우리가 이 코드를 생산 환경으로 미루면, 우리는 완전히 이와 같은 공백 화면을 볼 수 있을 것이다.

왜 우리는 아무것도 보이지 않습니까?
마찬가지로 React 문서에서 다음과 같은 해답을 찾을 수 있습니다.

As of React 16, errors that were not caught by any error boundary will result in unmounting of the whole React component tree.


개발 과정에서 창고 추적이 있는 빨간색 오류 메시지를 볼 수 있습니다. 오류가 어디에서 발생했는지 알려 줍니다.그러나 프로그램이 활성 상태일 때 공백 화면만 볼 수 있습니다.
이것은 프로그램이 원하는 행위가 아니다.
그러나 프로그램이 의외로 붕괴되면 오류가 발생할 수 있다는 것을 알려주거나 최소한 그들에게 보여줄 수 있는 방법이 있다.구성 요소 트리를 이른바 오류 경계에 포장할 수 있습니다.
오류 경계는 오류를 포착하고 사용자에게 반환 메시지를 표시할 수 있는 구성 요소입니다. 이 메시지는 사용자에게 오류가 발생했음을 알려 줍니다.오류를 제거하는 방법(즉, 페이지를 다시 로드하는 방법)에 대한 설명이 포함될 수 있습니다.
우리가 잘못된 경계를 사용할 수 있는 방법은 react-error-boundary포의 도움 아래이다.우리는 그것을 우리가 틀리기 쉽다고 생각하는 부품에 포장할 수 있다.또한 전체 애플리케이션 구성 요소 트리를 중심으로 다음을 수행할 수 있습니다.
import React from "react";
import { ErrorBoundary } from "react-error-boundary";

export default function App() {
  return (
    <ErrorBoundary FallbackComponent={ErrorFallback}>
      <Header />
    </ErrorBoundary>
  );
}

function Header() {
  const user = null;

  return <h1>Hello {user.name}</h1>;
}

function ErrorFallback({ error }) {
  return (
    <div role="alert">
      <p>Oops, there was an error:</p>
      <p style={{ color: "red" }}>{error.message}</p>
    </div>
  );
}
오류 메시지를 원하는 대로 표시하고 일반 구성 요소와 같은 스타일로 설정할 수도 있습니다.
확실히 오류가 발생했을 때, 우리가 얻은 결과는 훨씬 좋았다.

이 댓글 마음에 드세요?훈련소에 들어가다


The React Bootcamp은 당신이 알아야 할 러닝 리액트에 대한 모든 지식을 동영상, 메모지, 특별 보너스를 포함한 종합 패키지로 포장합니다.
수백 명의 개발자가 이미 파악하고 있는 내막 정보를 얻어 반응을 하고 이상적인 일을 찾으며 자신의 미래를 장악한다.

열릴 때 알림을 받으려면 여기를 누르십시오

좋은 웹페이지 즐겨찾기