programing

useEffect 후크 내부의 상태를 설정할 수 있습니까?

newsource 2022. 10. 27. 21:53

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>
  )
}

이렇게 요.setState에 inside inside inside useEffect무한 루프가 생성됩니다.이러한 루프는 아마 일으키고 싶지 않을 것입니다.그 규칙에는 몇 가지 예외가 있는데 나중에 이야기하겠습니다.

useEffect마다, 렌더링할 때, 렌더링할 때 .setState에서 사용하면 되고 컴포넌트가 됩니다.useEffect기타 등등.

중 죠.useState의 of의 useEffect 않습니다.는 빈 을 두 번째 입니다.useEffectuseEffect(() => {....}, []), 이펙트 1회 첫 마운트만.마운트 함수 에, 「마운트/마운트 함수」가 됩니다.이 기능은 구성 요소에서 데이터 가져오기를 수행할 때 구성 요소 상태에 요청 데이터를 저장하려는 경우 널리 사용됩니다.

이것은 장래의 목적을 위해서도 도움이 될 수 있습니다.

setState에서 를 사용해도 useEffect루프를 만들지 않으려면 이미 설명한 대로 주의를 기울이면 됩니다.

그러나 발생할 수 있는 문제는 이것뿐만이 아닙니다.아래를 참조해 주세요.

구성 상상해보세요.Comp를 수신한다.props로부터 A에 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.a ★★★★★★★★★★★★★★★★★」prop.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.

이게 누군가에게 도움이 됐으면 좋겠어!

한 이펙트 내에서 setState를 실행해도 이펙트는 항상 렌더링 단계가 완료된 후에 실행됩니다.다른 이펙트는 갱신된 상태를 읽어내고 렌더링 단계 후에만 이펙트에 액션을 수행합니다.

것이 좋을지도 , 만약 이 두 가지 행동을 같이 할 이 없다면bchanging a하는 것이 .

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보통보다 낫다useState복수의 서브값을 수반하는 복잡한 스테이트 로직이 있는 경우, 또는 다음의 스테이트가 앞의 것에 의존하는 경우. (React docs)

상태 변수 설정이 다른 상태 변수의 현재 값에 따라 달라지는 경우 두 변수 모두를 다음과 같이 바꿀 수 있습니다.useReducer[...] 글을 쓰고 있는 자신을 발견했을 때 setSomething(something => ...)대신 리덕터 사용을 검토하는 것이 좋습니다.(Dan Abramov, 과잉반응 블로그)

let MyComponent = () => {
  let [state, dispatch] = useReducer(reducer, { a: 1, b: 2 });

  useEffect(() => {
    console.log("Some effect with B");
  }, [state.b]);

  return (
    <div>
      <p>A: {state.a}, B: {state.b}</p>
      <button onClick={() => dispatch({ type: "SET_A", payload: 5 })}>
        Set A to 5 and Check B
      </button>
      <button onClick={() => dispatch({ type: "INCREMENT_B" })}>
        Increment B
      </button>
    </div>
  );
};

// B depends on A. If B >= A, then reset B to 1.
function reducer(state, { type, payload }) {
  const someCondition = state.b >= state.a;

  if (type === "SET_A")
    return someCondition ? { a: payload, b: 1 } : { ...state, a: payload };
  else if (type === "INCREMENT_B") return { ...state, b: state.b + 1 };
  return state;
}

ReactDOM.render(<MyComponent />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js" integrity="sha256-32Gmw5rBDXyMjg/73FgpukoTZdMrxuYW7tj8adbN8z4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js" integrity="sha256-bjQ42ac3EN0GqK40pC9gGi/YixvKyZ24qMP/9HiGW7w=" crossorigin="anonymous"></script>
<div id="root"></div>
<script>var { useReducer, useEffect } = React</script>


▶ 3. 다음 렌더링 전에 버튼을 클릭했을 때 첫 번째 효과가 발생하여 b가 변화하고 두 번째 효과가 발생할 수 있습니까?

useEffect렌더가 커밋되고 DOM 변경 내용이 적용된 후에는 항상 실행됩니다.첫 번째 효과는 발화, 변화b재연결을 일으킵니다.되면 두 됩니다.b★★★★★★★★★★★★★★★★★★.

let MyComponent = props => {
  console.log("render");
  let [a, setA] = useState(1);
  let [b, setB] = useState(2);

  let isFirstRender = useRef(true);

  useEffect(() => {
    console.log("useEffect a, value:", a);
    if (isFirstRender.current) isFirstRender.current = false;
    else setB(3);
    return () => {
      console.log("unmount useEffect a, value:", a);
    };
  }, [a]);
  useEffect(() => {
    console.log("useEffect b, value:", b);
    return () => {
      console.log("unmount useEffect b, value:", b);
    };
  }, [b]);

  return (
    <div>
      <p>a: {a}, b: {b}</p>
      <button
        onClick={() => {
          console.log("Clicked!");
          setA(5);
        }}
      >
        click me
      </button>
    </div>
  );
};

ReactDOM.render(<MyComponent />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js" integrity="sha256-32Gmw5rBDXyMjg/73FgpukoTZdMrxuYW7tj8adbN8z4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js" integrity="sha256-bjQ42ac3EN0GqK40pC9gGi/YixvKyZ24qMP/9HiGW7w=" crossorigin="anonymous"></script>
<div id="root"></div>
<script>var { useReducer, useEffect, useState, useRef } = React</script>


▶ 4. 이와 같은 코드 구조화에 성능 저하가 있습니까?

, ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★buseEffect★★★★★★에a브라우저에는 추가 레이아웃/표시 단계가 있습니다.이러한 효과는 사용자에게 표시될 수 있습니다. 수 없으면 주라useReducer try, change a a 、 [ a a a 、 [ ]b 말하다a★★★★

let MyComponent = () => {
  console.log("render");
  let [a, setA] = useState(1);
  let [b, setB] = useState(2);

  useEffect(() => {
    console.log("useEffect b, value:", b);
    return () => {
      console.log("unmount useEffect b, value:", b);
    };
  }, [b]);

  const handleClick = () => {
    console.log("Clicked!");
    setA(5);
    b >= 5 ? setB(1) : setB(b + 1);
  };

  return (
    <div>
      <p>
        a: {a}, b: {b}
      </p>
      <button onClick={handleClick}>click me</button>
    </div>
  );
};

ReactDOM.render(<MyComponent />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js" integrity="sha256-32Gmw5rBDXyMjg/73FgpukoTZdMrxuYW7tj8adbN8z4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js" integrity="sha256-bjQ42ac3EN0GqK40pC9gGi/YixvKyZ24qMP/9HiGW7w=" crossorigin="anonymous"></script>
<div id="root"></div>
<script>var { useReducer, useEffect, useState, useRef } = React</script>

상태를 변경할 필요가 있는지 여부를 확인하는 if-statement로 setState를 랩핑해 보십시오(예일 경우 변경, 그렇지 않으면 변경).return () => {}

예.,

useEffect(() => {
    if(a.currentCondition !== a.desiredCondition) {
        setA();
    }
    return cleanup;
}, [b])

언급URL : https://stackoverflow.com/questions/53715465/can-i-set-state-inside-a-useeffect-hook