[javascript] useEffect 후크 내부에 상태를 설정할 수 있습니까?

다른 상태에 의존하는 상태가 있다고 가정 해 보겠습니다 (예 : A가 변경되면 B가 변경되기를 원합니다).

A를 관찰하고 useEffect 후크 내부에 B를 설정하는 후크를 만드는 것이 적절합니까?

버튼을 클릭하면 첫 번째 효과가 발생하여 다음 렌더링 전에 b가 변경되어 두 번째 효과가 발생하도록 효과가 계단식으로 표시됩니까? 이와 같은 코드를 구조화하는 데 성능 저하가 있습니까?

let MyComponent = props => {
  let [a, setA] = useState(1)
  let [b, setB] = useState(2)
  useEffect(
    () => {
      if (/*some stuff is true*/) {
        setB(3)
      }
    },
    [a],
  )
  useEffect(
    () => {
      // do some stuff
    },
    [b],
  )

  return (
    <button
      onClick={() => {
        setA(5)
      }}
    >
      click me
    </button>
  )
}



답변

효과는 항상 렌더링 단계가 완료된 후에 실행됩니다. 한 효과 내에서 State를 설정하더라도 다른 효과는 업데이트 된 상태를 읽고 렌더링 단계 후에 만 ​​작업을 수행합니다.

동일한 논리를 실행하려는 경우 b이외에 다른 이유로 인해 변경 될 수 있는 가능성이없는 한 동일한 효과로 두 작업을 모두 수행하는 것이 더 좋습니다.changing a


답변

일반적으로 setState내부 useEffect를 사용하면 원하지 않는 무한 루프가 생성됩니다. 나중에 다루게 될 규칙에는 몇 가지 예외가 있습니다.

useEffect는 각 렌더링 후 호출되고 setState내부에서 사용되면 구성 요소가 다시 렌더링되어 호출 useEffect등을 수행합니다.

useStateinside of 를 사용 useEffect하면 무한 루프가 발생하지 않는 인기있는 경우 중 하나는 useEffectlike에 대한 두 번째 인수로 빈 배열을 전달할 때 useEffect(() => {....}, [])입니다. 즉, 효과 함수는 첫 번째 마운트 / 렌더링 이후에만 한 번 호출되어야합니다. 구성 요소에서 데이터 가져 오기를 수행하고 요청 데이터를 구성 요소의 상태로 저장하려는 경우 널리 사용됩니다.


답변

향후 목적을 위해 다음도 도움이 될 수 있습니다.

useEffect이미 설명한대로 루프를 생성하지 않도록주의를 기울여야 하는 경우 setState를 사용 하는 것이 좋습니다.

그러나 이것이 발생할 수있는 유일한 문제는 아닙니다. 아래를 참조하십시오.

부모로부터 Comp받는 구성 요소 가 props있고 의 상태 props를 설정하려는 변경 에 따라 있다고 상상해보십시오 Comp. 어떤 이유로 각 소품마다 다른 변경해야합니다 useEffect.

하지 마십시오

useEffect(() => {
  setState({ ...state, a: props.a });
}, [props.a]);

useEffect(() => {
  setState({ ...state, b: props.b });
}, [props.b]);

이 예에서 볼 수 있듯이 https://codesandbox.io/s/confident-lederberg-dtx7w 에서 볼 수 있듯이 상태를 변경하지 않을 수 있습니다.

때문에이 예에서 일어나는 이유는 그건 모두 useEffects이 같은 실행주기를 반응 은 모두 변경할 때 prop.aprop.b의 가치, 그래서 {...state}당신이 할 때이 setState정확히 모두에서 동일 useEffect는 같은 맥락에서 때문이다. 두 번째를 실행 setState하면 첫 번째setState .

이 대신 수행

이 문제에 대한 해결책은 기본적으로 다음 setState과 같이 호출하는 것입니다.

useEffect(() => {
  setState(state => ({ ...state, a: props.a }));
}, [props.a]);

useEffect(() => {
  setState(state => ({ ...state, b: props.b }));
}, [props.b]);

여기에서 솔루션을 확인하십시오 : https://codesandbox.io/s/mutable-surf-nynlx

이제 setState.

나는 이것이 누군가에게 도움이되기를 바랍니다!


답변

useEffect특정 소품이나 상태에 연결할 수 있습니다. 따라서 무한 루프 훅을 피하기 위해해야 ​​할 일은 어떤 변수 나 상태를 바인딩하는 것입니다.

예를 들면 :

useEffect(myeffectCallback, [])

위의 효과는 구성 요소가 렌더링 된 후에 만 ​​발생합니다. 이것은 componentDidMount수명주기 와 유사합니다.

const [something, setSomething] = withState(0)
const [myState, setMyState] = withState(0)
useEffect(() => {
  setSomething(0)
}, myState)

위의 효과는 내 상태가 변경된 경우에만 componentDidUpdate발생합니다. 이것은 모든 변경 상태가 발생하는 것은 아니라는 점 을 제외하고 는 비슷 합니다.

링크를 통해 자세한 내용을 읽을 수 있습니다.


답변

▶ 1. useEffect 후크 내부에 상태를 설정할 수 있나요?

원칙적으로 내부 useEffect렌더링 중을 포함하여 필요한 곳에 상태를 자유롭게 설정할 수 있습니다 . 후크를 deps적절하게 설정하거나 조건부로 상태 를 설정하여 무한 루프를 피하십시오 .


▶ 2. 다른 상태에 의존하는 상태가 있다고 가정 해 보겠습니다. A를 관찰하고 useEffect 후크 내부에 B를 설정하는 후크를 만드는 것이 적절합니까?

다음에 대한 고전적인 사용 사례를 설명 했습니다 useReducer.

useReducer일반적으로 여러 하위 값 을 포함 하는 복잡한 상태 논리가 있거나 다음 상태가 이전 상태에 의존 하는 useState경우 보다 선호됩니다 . ( React 문서 )

상태 변수 설정 이 다른 상태 변수 의 현재 값에 따라 달라지는 경우 둘 다로 대체 할 수 있습니다 . […] 글을 쓰는 자신을 발견하면 대신 감속기를 사용하는 것을 고려하는 것이 좋습니다. (useReducer setSomething(something => ...) Dan Abramov, Overreacted 블로그 )


▶ 3. 버튼을 클릭하면 첫 번째 효과가 실행되어 다음 렌더링 전에 b가 변경되어 두 번째 효과가 실행되도록 효과가 계단식으로 표시됩니까?

useEffect항상 렌더링이 커밋되고 DOM 변경 사항이 적용된 후에 실행 됩니다. 첫 번째 효과가 발생하고 변경 b되고 다시 렌더링됩니다. 이 렌더가 완료된 후 두 번째 효과는b 변경 사항 됩니다.


▶ 4. 이와 같이 코드를 구조화하면 성능상의 단점이 있습니까?

예. 상태 변경을 래핑하여 b분리에 useEffect대한 a이러한 영향은 잠재적으로 사용자가 볼 수있다 – 브라우저는 추가적인 레이아웃 / 페인트 위상을 갖는다. useReducer시도해 보고 싶은 방법이 없다면 직접 b상태를 변경할 수 있습니다 a.


답변