programing

Lodash가 React에서 작동하지 않음

newnotes 2023. 3. 16. 21:47
반응형

Lodash가 React에서 작동하지 않음

먼저 코드를 확인하는 것이 가장 좋습니다.

import React, { Component } from 'react';
import _ from 'lodash';
import Services from 'Services'; // Webservice calls

export default class componentName extends Component {
  constructor(props) {
    super(props);
    this.state = {
      value: this.props.value || null
    }
  }

  onChange(value) {
    this.setState({ value });

    // This doesn't call Services.setValue at all
    _.debounce(() => Services.setValue(value), 1000);
  }

  render() {
    return (
      <div>
        <input 
          onChange={(event, value) => this.onChange(value)}
          value={this.state.value}
        />
      </div>
    )
  }
}

간단한 입력입니다.컨스트럭터 안에서 그것은 잡는다.value구성 요소의 로컬 상태를 설정합니다(사용 가능한 경우).

그리고 나서onChange의 기능input상태를 업데이트한 후 웹 서비스 엔드포인트에 호출하여 다음 명령을 사용하여 새 값을 설정하려고 합니다.Services.setValue().

동작하는 것은, 다음의 설정을 실시했을 경우입니다.debounce바로 옆에서onChange다음과 같이 입력합니다.

<input 
  value={this.state.value} 
  onChange={_.debounce((event, value) => this.onChange(value), 1000)} 
/>

그러나this.setState는 1000밀리초마다 호출되어 뷰를 갱신합니다.텍스트 필드에 입력하는 것은 1초 후에 표시되기 때문에 이상하게 보입니다.

이럴 때 어떻게 해야 하죠?

이 문제는 debounce 함수를 호출하지 않기 때문에 발생합니다.다음 방법으로 실행할 수 있습니다.

export default class componentName extends Component {
  constructor(props) {
    super(props);
    this.state = {
      value: this.props.value || null
    }
    this.servicesValue = _.debounce(this.servicesValue, 1000);
  }

  onChange(value) {
    this.setState({ value });
    this.servicesValue(value);
  }
  servicesValue = (value) => {
      Services.setValue(value)
  }
  render() {
    return (
      <div>
        <input 
          onChange={(event, value) => this.onChange(value)}
          value={this.state.value}
        />
      </div>
    )
  }
}

Throttle/Debounce가 동작하지 않기 때문에 여기에 오신 분들을 위한 솔루션FunctionComponent- useRef()를 통해 디버깅된 함수를 저장해야 합니다.

export const ComponentName = (value = null) => {
  const [inputValue, setInputValue] = useState(value);

  const setServicesValue = value => Services.setValue(value);

  const setServicesValueDebounced = useRef(_.debounce(setServicesValue, 1000));

  const handleChange = ({ currentTarget: { value } }) => {
    setInputValue(value);
    setServicesValueDebounced.current(value);
  };

  return <input onChange={handleChange} value={inputValue} />;
};

이 미디어 기사에서는 어떤 일이 일어나는지 완벽하게 설명합니다.

함수 내부의 로컬 변수는 콜마다 기한이 만료됩니다.컴포넌트를 재평가할 때마다 로컬 변수가 다시 초기화됩니다.스로틀 및 데바운스는 다음을 사용하여 작동합니다.window.setTimeout()막후에서함수 컴포넌트가 평가될 때마다 새로 등록됩니다.setTimeout콜백그래서 저희는useRef()반환된 값으로서 후크하다useRef()는 기능 컴포넌트가 실행될 때마다 재검출되지 않습니다.유일한 불편한 점은 저장된 값에 액세스해야 한다는 것입니다..current소유물.

작은 샌드박스를 만들었습니다.lodash.throttle그리고.lodash.debounce두 가지 모두 실험하고 적절한 동작을 선택할 수 있는 패키지

React 기능 컴포넌트의 경우 디폴트로는 데바운스는 동작하지 않습니다.동작하려면 , 다음의 조작을 실시할 필요가 있습니다.

const debouncedFunction= React.useCallback(debounce(functionToCall, 400), []);

useCallback은 debounce에 의해 반환된 함수를 사용하여 예상대로 작동합니다.단, 디버깅된 함수 내에서 상태 변수를 사용하는 경우(보통 이 경우)는 조금 더 복잡합니다.

React.useCallback(debounce(fn, timeInMs), [])

React.useCallback의 두 번째 인수는 의존관계에 대한 것입니다.디버깅된 함수에서 상태 변수 또는 프로포 변수를 사용하는 경우 기본적으로는 오래된 버전의 상태 변수가 사용됩니다.이 경우 함수는 필요한 변수가 아닌 변수의 이력 값을 사용합니다.이 문제를 해결하려면 React.useEffect에서처럼 상태 변수를 포함해야 합니다.

React.useCallback(debounce(fn, timeInMs), [stateVariable1, stateVariable2])

이 실장에서는, 목적을 해결할 수 있습니다.그러나 디버깅된 함수는 의존관계가 변경됨에 따라 상태 변수(stateVariable1, stateVariable2)가 전달될 때마다 호출됩니다.입력 필드처럼 제어된 컴포넌트를 사용하는 경우에는 특히 필요하지 않을 수 있습니다.

제가 깨달은 최고의 솔루션은 기능 컴포넌트를 클래스 기반 컴포넌트로 변경하는 데 시간을 두고 다음 구현을 사용하는 것입니다.

constructor(props)
    {
        super();
        this.state = {...};
        this.functionToCall= debounce(this.functionToCall.bind(this), 400, {'leading': true});
    }

리액트 기능을 사용하는 분들을 위해 후크를 썼습니다.

이것은 타이프스크립트이지만, 자바스크립트 어플리케이션에서 사용하는 타입 주석을 무시할 수 있습니다.

| use-communce.ts |

import { debounce, DebounceSettings } from 'lodash'
import { useRef } from 'react'

interface DebouncedArgs<T> {
  delay?: number
  callback?: (value: T) => void
  debounceSettings?: DebounceSettings
}



export const useDebounce = <T = unknown>({ callback, debounceSettings, delay = 700 }: DebouncedArgs<T>) => {
  const dispatchValue = (value: T) => callback?.(value)

  const setValueDebounced = useRef(debounce(dispatchValue, delay, { ...debounceSettings, maxWait: debounceSettings?.maxWait || 1400 }))

  return (value: T) => setValueDebounced.current(value)
}

| 사용방법:|

export const MyInput: FC = () => {
  const [value, setValue] = useState<string>('')
  const debounce = useDebounce({ callback: onChange })

  const handleOnInput = (evt: FormEvent<HTMLInputElement>) => {
    const { value } = evt.currentTarget
    setValue(value)
    debounce(value)
  }

  function onChange(value: string) {
    // send request to the server for example
    console.log(value)
  }

  return <input value={value} onInput={handleOnInput} />
}

기능 컴포넌트 솔루션 - useCallback 사용

export const ComponentName = (value = null) => {
  const [inputValue, setInputValue] = useState(value);

  const setServicesValue = value => Services.setValue(value);

  const setServicesValueDebounced = useCallback(_.debounce(setServicesValue, 500), []);

  const handleChange = ({ currentTarget: { value } }) => {
    setInputValue(value);
    setServicesValueDebounced(value);
  };

  return <input onChange={handleChange} value={inputValue} />;
};

언급URL : https://stackoverflow.com/questions/47809666/lodash-debounce-not-working-in-react

반응형