source

리액트 입력에 의한 Lodash 데바운스

nicesource 2023. 3. 25. 11:28
반응형

리액트 입력에 의한 Lodash 데바운스

input onChange 이벤트에서 호출된 검색 기능에 lodash를 사용한 디버깅을 추가하려고 합니다.아래 코드는 'function expected' 유형 오류를 생성하며, 이는 lodash가 function을 예상하고 있기 때문에 이해합니다.올바른 방법은 무엇이며, 모두 인라인으로 할 수 있습니까?나는 지금까지 SO에 거의 모든 예를 시도했지만 소용이 없었다.

search(e){
 let str = e.target.value;
 debounce(this.props.relay.setVariables({ query: str }), 500);
},

기능적 반응 구성 요소를 사용하여useCallback.useCallback는 디바운스 기능을 메모하기 때문에 컴포넌트가 재렌더될 때 반복적으로 재생성되지 않습니다.없이.useCallback데바운스 기능은 다음 키 스트로크와 동기화되지 않습니다.

`

import {useCallback} from 'react';
import _debounce from 'lodash/debounce';
import axios from 'axios';

function Input() {
    const [value, setValue] = useState('');

    const debounceFn = useCallback(_debounce(handleDebounceFn, 1000), []);

    function handleDebounceFn(inputValue) {
        axios.post('/endpoint', {
          value: inputValue,
        }).then((res) => {
          console.log(res.data);
        });
    }


    function handleChange (event) {
        setValue(event.target.value);
        debounceFn(event.target.value);
    };

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

`

데바운스 함수는 다음과 같이 JSX에서 인라인으로 전달하거나 클래스 메서드로 직접 설정할 수 있습니다.

search: _.debounce(function(e) {
  console.log('Debounced Event:', e);
}, 1000)

바이올린: https://jsfiddle.net/woodenconsulting/69z2wepo/36453/

es2015+를 사용하는 경우 debounce 메서드를 직접 정의할 수 있습니다.constructor또는 다음과 같은 라이프 사이클 방식으로componentWillMount.

예:

class DebounceSamples extends React.Component {
  constructor(props) {
    super(props);

    // Method defined in constructor, alternatively could be in another lifecycle method
    // like componentWillMount
    this.search = _.debounce(e => {
      console.log('Debounced Event:', e);
    }, 1000);
  }

  // Define the method directly in your class
  search = _.debounce((e) => {
    console.log('Debounced Event:', e);
  }, 1000)
}

하루 종일 검색해서 이렇게 했어요.

const MyComponent = (props) => {
  const [reload, setReload] = useState(false);

  useEffect(() => {
    if(reload) { /* Call API here */ }
  }, [reload]);

  const callApi = () => { setReload(true) }; // You might be able to call API directly here, I haven't tried
  const [debouncedCallApi] = useState(() => _.debounce(callApi, 1000));

  function handleChange() { 
    debouncedCallApi(); 
  }

  return (<>
    <input onChange={handleChange} />
  </>);
}

그건 쉬운 질문이 아니야

한편으로, 에러 발생을 회피하기 위해서는, 이 문제를 정리할 필요가 있습니다.setVariables함수의 경우:

 search(e){
  let str = e.target.value;
  _.debounce(() => this.props.relay.setVariables({ query: str }), 500);
}

반면에, 나는 비난 논리가 릴레이 안에 삽입되어야 한다고 믿는다.

많은 답변이 너무 복잡하거나 정확하지 않다는 것을 알게 되었습니다(즉, 실제로는 비난하지 않습니다).체크할 수 있는 간단한 솔루션은 다음과 같습니다.

const [count, setCount] = useState(0); // simple check debounce is working
const handleChangeWithDebounce = _.debounce(async (e) => {
    if (e.target.value && e.target.value.length > 4) {
        // TODO: make API call here
        setCount(count + 1);
        console.log('the current count:', count)
    }
}, 1000);
<input onChange={handleChangeWithDebounce}></input>

이 답변에 대한 개선: https://stackoverflow.com/a/67941248/2390312

사용.useCallback그리고.debounce에슬린트를 일으키는 것으로 알려져 있다.exhaustive deps경고합니다.

기능 컴포넌트 및useMemo

import { useMemo } from 'react';
import { debounce } from 'lodash';
import axios from 'axios';

function Input() {
    const [value, setValue] = useState('');

    const debounceFn = useMemo(() => debounce(handleDebounceFn, 1000), []);

    function handleDebounceFn(inputValue) {
        axios.post('/endpoint', {
          value: inputValue,
        }).then((res) => {
          console.log(res.data);
        });
    }


    function handleChange (event) {
        setValue(event.target.value);
        debounceFn(event.target.value);
    };

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

사용하고 있습니다.useMemo메모된 값을 반환하려면 이 값은 에서 반환되는 함수입니다.debounce

이벤트 오브젝트(e)에서 e.target.value와 같은 것을 사용하는 경우 데바운스 함수를 통과하면 원래 이벤트 값이 null이 된다는 응답도 있습니다.

다음 오류 메시지를 참조하십시오.

경고:이 가상 이벤트는 성능상의 이유로 재사용됩니다.이 경우 해당 자산에 액세스하고 있는 것입니다.nativeEvent공개/검증된 모의 이벤트에 대한 것입니다.이것은 null로 설정되어 있습니다.원래 모의 이벤트를 보관해야 할 경우 event.persist()를 사용합니다.

메시지에서 알 수 있듯이 이벤트 함수에 e.persist()를 포함해야 합니다.예를 들어 다음과 같습니다.

const onScroll={(e) => {
  debounceFn(e);
  e.persist();
}}

그 후 react.useCallback()을 이용하려면 debounceFn을 반환문 밖에서 스코프해야 합니다.이것은 필수입니다.debounceFn은 다음과 같습니다.

const debounceFn = React.useCallback(
  _.debounce((e) => 
      calculatePagination(e), 
      500, {
            trailing: true,
      }
  ),
  []
);

@Aximili

const [debouncedCallApi] = useState(() => _.debounce(callApi, 1000));

에는 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★useCallback:

const [searchFor, setSearchFor] = useState('');

const changeSearchFor = debounce(setSearchFor, 1000);
const handleChange = useCallback(changeSearchFor, []);

고객님의 경우는 다음과 같습니다.

search = _.debounce((e){
 let str = e.target.value;
 this.props.relay.setVariables({ query: str });
}, 500),
class MyComp extends Component {
  debounceSave;
  constructor(props) {
    super(props);
  }
  this.debounceSave = debounce(this.save.bind(this), 2000, { leading: false, trailing: true });
}

save()는 호출되는 함수입니다.

debounce Save()는 실제로 호출하는 함수입니다(여러 번).

이 방법은 효과가 있었습니다.

handleChange(event) {
  event.persist();
  const handleChangeDebounce = _.debounce((e) => {
    if (e.target.value) {
      // do something
    } 
  }, 1000);
  handleChangeDebounce(event);
}

이것이 FC의 올바른 접근법입니다.

Aximili는 트리거에 한 번만 응답한다.

import { SyntheticEvent } from "react"

export type WithOnChange<T = string> = {
    onChange: (value: T) => void
}

export type WithValue<T = string> = {
    value: T
}

//  WithValue & WithOnChange
export type VandC<A = string> = WithValue<A> & WithOnChange<A>

export const inputValue = (e: SyntheticEvent<HTMLElement & { value: string }>): string => (e.target as HTMLElement & { value: string }).value

const MyComponent: FC<VandC<string>> = ({ onChange, value }) => {
    const [reload, setReload] = useState(false)
    const [state, setstate] = useState(value)
    useEffect(() => {
        if (reload) {
            console.log('called api ')
            onChange(state)
            setReload(false)
        }
    }, [reload])

    const callApi = () => {

        setReload(true)
    } // You might be able to call API directly here, I haven't tried
    const [debouncedCallApi] = useState(() => _.debounce(callApi, 1000))

    function handleChange(x:string) {
        setstate(x)
        debouncedCallApi()
    }

    return (<>
        <input
            value={state} onChange={_.flow(inputValue, handleChange)} />
    </>)
}


    const delayedHandleChange = debounce(eventData => someApiFunction(eventData), 500);

const handleChange = (e) => {
        let eventData = { id: e.id, target: e.target };
        delayedHandleChange(eventData);
    }

언급URL : https://stackoverflow.com/questions/36294134/lodash-debounce-with-react-input

반응형