programing

파라미터를 사용하여 useCallback 응답

muds 2023. 3. 12. 11:23
반응형

파라미터를 사용하여 useCallback 응답

리액트 사용useCallback훅은 본질적으로 그냥 감싸는 것이다useMemo컴포넌트의 소품 내에 새로운 기능 인스턴스가 지속적으로 생성되지 않도록 하는 기능에 특화되어 있습니다.이 질문은 메모화로 작성된 콜백에 인수된 내용을 전달할 필요가 있는 경우입니다.

예를 들어, 콜백은 이렇게 작성됩니다.

const Button: React.FunctionComponent = props => {
    const onClick = React.useCallback(() => alert('Clicked!'), [])
    return <button onClick={onClick}>{props.children}</button>
}

는 메모화된 콜백의 단순한 예이며 작업을 수행하기 위해 외부 값이 전달되지 않습니다.단, 일반적인 메모화된 콜백을 작성하려면React.Dipatch<React.SetStateAction>함수 타입을 지정하면 인수가 필요합니다.예를 들어 다음과 같습니다.

const Button: React.FunctionComponent = props => {
    const [loading, setLoading] = React.useState(false)
    const genericSetLoadingCb = React.useCallback((x: boolean) => () => setLoading(x), [])

    return <button onClick={genericSetLoadingCb(!loading)}>{props.children}</button>
}

제 머릿속에서는, 이것은 다음과 같은 것을 하는 것과 같은 것 같습니다.

const Button: React.FunctionComponent = props => {
    const [loading, setLoading] = React.useState(false)
    return <button onClick={() => setLoading(!loading)}>{props.children}</button>
}

그것은 여전히 모든 렌더링에 새로운 함수를 만들고 있을 것이기 때문에 함수를 메모하는 목적을 좌절시킬 것이다.genericSetLoadingCb(false)각 렌더링에 대해 새로운 함수를 반환하는 것입니다.

이 이해가 올바른가, 아니면 인수와 함께 기술된 패턴이 메모화의 이점을 유지하고 있는가?

조금 다른 사용 사례에 대한 답변을 드리겠지만, 여전히 귀하의 질문에 답변할 수 있습니다.

동기 및 문제 설명

이하를 검토해 봅시다(고객님의 경우와 비슷합니다).genericSetLoadingCb) 고차 함수genericCb:

  const genericCb = React.useCallback(
    (param) => (e) => setState({ ...state, [param]: e.target.value }),
    []
  );

예를 들어 다음과 같은 상황에서 사용합니다.Input는 React.memo를 사용하여 작성된 메모화된 컴포넌트입니다.

  <Input value={state.firstName} onChange={genericCb('firstName')} />

부터Input메모화된 컴포넌트입니다.이 기능을 생성해 주세요. genericCb('firstName')메모화된 컴포넌트가 불필요하게 재작성되지 않도록 재작성 시에도 동일하게 유지됩니다.

이하에서는, 이것을 실현하는 방법에 대해 설명합니다.

솔루션

자, 우리가 만든 방법은genericCb위는 (사용에 의해) 렌더링 간에 동일하게 유지되도록 하고 있습니다.useCallback).

단, 전화할 때마다genericCb다음과 같이 새로운 기능을 만들 수 있습니다.

genericCb("firstName") 

반환되는 함수는 각 렌더링에서 계속 다릅니다.또한 일부 입력에 대해 반환된 함수가 메모되도록 하려면 다음과 같은 메모화 방법을 추가로 사용해야 합니다.

  import memoize from "fast-memoize";
  ....

  const genericCb = React.useCallback(
    memoize((param) => (e) => setState({ ...state, [param]: e.target.value })),
    []
  );

지금 전화하면genericCb("firstName")함수를 생성하기 위해 각 렌더링에 동일한 함수를 반환합니다. 단, 동일한 함수도 유지됩니다.

언급

위의 솔루션에서 지적한 바와 같이useCallback경고하는 것 같습니다(단, 제 프로젝트에는 없었습니다).

React Hook useCallback이 의존관계를 알 수 없는 함수를 수신했습니다.대신 인라인 함수를 전달합니다.

것 .useCallback이 github 스레드를 기반으로 이 경고를 없애기 위해 찾은 솔루션은useMemo를 내다useCallback음음음같 뭇매하다

// Use this; this doesn't produce the warning anymore  
const genericCb = React.useMemo(
    () =>
      memoize(
        (param) => (e) => setState({ ...state, [param]: e.target.value })
      ),
    []
  );

, 메모의 은, 「」를 사용하지 않고, 「메모화」를 사용하는 것에 .useCallback (오류)useMemo업데이트에서와 같이)는 기능하지 않습니다.다음 렌더링에서는 다음과 같이 새로고침에서 메모가 호출됩니다.

let memoized = memoize(fn)
 
memoized('foo', 3, 'bar')
memoized('foo', 3, 'bar') // cache hit

memoized = memoize(fn); // without useCallback (or useMemo) this would happen on next render 

// Now the previous cache is lost

가능한 인수값별로 메모화된 콜백 맵을 작성할 것을 권장합니다.

const genericSetLoadingCb = React.useMemo(() =>
  {
    [true]: () => setLoading(true),
    [false]: () => setLoading(false),
  },
  []
);

따라서 메모화된 버전은 각 값에 대해 동일합니다.

return <button onClick={genericSetLoadingCb[!loading]}>{props.children}</button>

언급URL : https://stackoverflow.com/questions/61255053/react-usecallback-with-parameter

반응형