programing

React Hooks useEffect에서 oldValues와 newValues를 비교하는 방법은 무엇입니까?

yoursource 2021. 1. 14. 23:25
반응형

React Hooks useEffect에서 oldValues와 newValues를 비교하는 방법은 무엇입니까?


rate, sendAmount 및 receiveAmount의 세 가지 입력이 있다고 가정 해 보겠습니다. useEffect diffing params에 3 개의 입력을 넣었습니다. 규칙은 다음과 같습니다.

  • sendAmount가 변경되면 계산합니다. receiveAmount = sendAmount * rate
  • receiveAmount가 변경되면 계산합니다. sendAmount = receiveAmount / rate
  • 속도를 변경 한 경우, 내가 계산할 receiveAmount = sendAmount * ratesendAmount > 0또는 내가 계산할 sendAmount = receiveAmount / ratereceiveAmount > 0

다음은 문제를 보여주는 codesandbox https://codesandbox.io/s/pkl6vn7x6j 입니다.

이 경우 3 개의 핸들러를 만드는 대신에 oldValuesand newValueslike 를 비교하는 방법 componentDidUpdate이 있습니까?

감사


다음은 https://codesandbox.io/s/30n01w2r06의 최종 솔루션입니다.usePrevious

이 경우 useEffect각 변경 사항이 동일한 네트워크 호출로 이어지기 때문에 여러 개를 사용할 수 없습니다 . 그래서 changeCount변경 사항을 추적 하는데도 사용 합니다. changeCount또한 로컬에서만 변경 사항을 추적하는 데 도움 되므로 서버 변경으로 인한 불필요한 네트워크 호출을 방지 할 수 있습니다.


useRef를 사용하여 이전 소품 을 제공하는 사용자 지정 후크를 작성할 수 있습니다.

function usePrevious(value) {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  });
  return ref.current;
}

그리고 그것을에서 사용하십시오 useEffect

const Component = (props) => {
    const {receiveAmount, sendAmount } = props
    const prevAmount = usePrevious({receiveAmount, sendAmount});
    useEffect(() => {
        if(prevAmount.receiveAmount !== receiveAmount) {

         // process here
        }
        if(prevAmount.sendAmount !== sendAmount) {

         // process here
        }
    }, [receiveAmount, sendAmount])
}

그러나 useEffect개별적으로 처리하려는 각 변경 ID에 대해 두 개를 별도로 사용하면 읽고 이해하는 것이 더 명확하고 아마도 더 낫고 명확합니다.


옵션 1-UseCompare 후크

현재 값을 이전 값과 비교하는 것은 일반적인 패턴이며 구현 세부 정보를 숨기는 고유 한 사용자 지정 후크를 정당화합니다.

const useCompare = (val: any) => {
    const prevVal = usePrevious(val)
    return prevVal !== val
}

const usePrevious = (value) {
    const ref = useRef();
    useEffect(() => {
      ref.current = value;
    });
    return ref.current;
}

const Component = (props) => {
  ...
  const hasVal1Changed = useCompare(val1)
  const hasVal2Changed = useCompare(val2);
  useEffect(() => {
    if (hasVal1Changed ) {
      console.log("val1 has changed");
    }
    if (hasVal2Changed ) {
      console.log("val2 has changed");
    }
  });

  return <div>...</div>;
};

데모

옵션 2-값이 변경되면 useEffect 실행

const Component = (props) => {
  ...
  useEffect(() => {
    console.log("val1 has changed");
  }, [val1]);
  useEffect(() => {
    console.log("val2 has changed");
  }, [val2]);

  return <div>...</div>;
};

데모


Incase anybody is looking for a TypeScript version of usePrevious:

import { useEffect, useRef } from "react";

const usePrevious = <T>(value: T) => {
  const ref = useRef<T>();
  useEffect(() => {
    ref.current = value;
  });
  return ref.current;
};

Since state isn't tightly coupled with component instance in functional components, previous state cannot be reached in useEffect without saving it first, for instance, with useRef. This also means that state update was possibly incorrectly implemented in wrong place because previous state is available inside setState updater function.

This is a good use case for useReducer which provides Redux-like store and allows to implement respective pattern. State updates are performed explicitly, so there's no need to figure out which state property is updated; this is already clear from dispatched action.

Here's an example what it may look like:

function reducer({ sendAmount, receiveAmount, rate }, action) {
  switch (action.type) {
    case "sendAmount":
      sendAmount = action.payload;
      return {
        sendAmount,
        receiveAmount: sendAmount * rate,
        rate
      };
    case "receiveAmount":
      receiveAmount = action.payload;
      return {
        sendAmount: receiveAmount / rate,
        receiveAmount,
        rate
      };
    case "rate":
      rate = action.payload;
      return {
        sendAmount: receiveAmount ? receiveAmount / rate : sendAmount,
        receiveAmount: sendAmount ? sendAmount * rate : receiveAmount,
        rate
      };
    default:
      throw new Error();
  }
}

function handleChange(e) {
  const { name, value } = e.target;
  dispatch({
    type: name,
    payload: value
  });
}

...
const [state, dispatch] = useReducer(reducer, {
  rate: 2,
  sendAmount: 0,
  receiveAmount: 0
});
...

For really simple prop comparison you can use useEffect and useState to easily check to see if a prop has updated.

const myComponent = ({ prop }) => {
  const [propHasChanged, setPropHasChanged] = useState(false)
  useEffect(() => {
    setHasPropChanged(true)
  }, [prop])

  if(propHasChanged){
    ~ do stuff here ~
  }
}

useEffect checks to see if the prop has changed, updates the state to say that it has and allows your conditional code to run.

ReferenceURL : https://stackoverflow.com/questions/53446020/how-to-compare-oldvalues-and-newvalues-on-react-hooks-useeffect

반응형