참조가 DOM 요소를 가리킬 때 useEffect의 종속성으로 ref.current를 사용하는 것이 안전합니까?
ref는 가변 컨테이너이므로 다음 목록에 기재되어서는 안 됩니다.useEffect
단, 의 의존관계ref.current
값이 바뀔 수 있습니다.
참조를 사용하여 다음과 같은 DOM 요소를 저장하는 경우<div ref={ref}>
그 요소에 의존하는 커스텀 훅을 개발하면 다음과 같이 됩니다.ref.current
는 컴포넌트가 조건부로 반환되는 경우 다음과 같이 시간이 지남에 따라 변경될 수 있습니다.
const Foo = ({inline}) => {
const ref = useRef(null);
return inline ? <span ref={ref} /> : <div ref={ref} />;
};
커스텀 이펙트를 수신해도 안전한가?ref
목적과 용도ref.current
의존관계로요?
const useFoo = ref => {
useEffect(
() => {
const element = ref.current;
// Maybe observe the resize of element
},
[ref.current]
);
};
이 코멘트를 읽은 적이 있는데, 레퍼런스는 다음 코멘트를useEffect
하지만 어떤 경우든 알 수 없는 경우라도ref.current
변경되지만 효과는 트리거되지 않습니다.
이 문제가 시사하는 바와 같이 콜백 ref를 사용해야 하는데, ref as 인수는 여러 후크를 통합하는 데 매우 편리합니다.
const ref = useRef(null);
useFoo(ref);
useBar(ref);
사용자가 콜백 참조를 작성하도록 강제되기 때문에 콜백 참조를 사용하는 것은 어렵습니다.
const fooRef = useFoo();
const barRef = useBar();
const ref = element => {
fooRef(element);
barRef(element);
};
<div ref={ref} />
이래서 사용해도 안전한지 물어보는 거야ref.current
에useEffect
.
참조를 변환해도 렌더가 트리거되지 않기 때문에 안전하지 않습니다. 따라서 이 작업은useEffect
.
React Hook useEffect에는 'ref.current'라는 불필요한 종속성이 있습니다.제외하거나 종속 어레이를 제거합니다.'ref.current'와 같은 변환 가능한 값은 변환해도 구성 요소가 다시 렌더링되지 않으므로 유효한 종속성이 아닙니다.(예비/예비/예비/예비)
안티 패턴의 예를 다음에 나타냅니다.
const Foo = () => {
const [, render] = useReducer(p => !p, false);
const ref = useRef(0);
const onClickRender = () => {
ref.current += 1;
render();
};
const onClickNoRender = () => {
ref.current += 1;
};
useEffect(() => {
console.log('ref changed');
}, [ref.current]);
return (
<>
<button onClick={onClickRender}>Render</button>
<button onClick={onClickNoRender}>No Render</button>
</>
);
};
이 패턴과 관련된 실제 사용 사례는 요소가 마운트 해제된 경우에도 지속적인 참조를 원하는 경우입니다.
다음 예에서는 마운트 해제 시 요소의 크기를 유지할 수 없습니다.사용해보도록 하겠습니다.useRef
와 함께useEffect
콤보이지만 동작하지 않습니다.
// BAD EXAMPLE, SEE SOLUTION BELOW
const Component = () => {
const ref = useRef();
const [isMounted, toggle] = useReducer((p) => !p, true);
const [elementRect, setElementRect] = useState();
useEffect(() => {
console.log(ref.current);
setElementRect(ref.current?.getBoundingClientRect());
}, [ref.current]);
return (
<>
{isMounted && <div ref={ref}>Example</div>}
<button onClick={toggle}>Toggle</button>
<pre>{JSON.stringify(elementRect, null, 2)}</pre>
</>
);
};
놀랍게도 이걸 고치려면node
직접 기능을 메모하면서useCallback
:
// GOOD EXAMPLE
const Component = () => {
const [isMounted, toggle] = useReducer((p) => !p, true);
const [elementRect, setElementRect] = useState();
const handleRect = useCallback((node) => {
setElementRect(node?.getBoundingClientRect());
}, []);
return (
<>
{isMounted && <div ref={handleRect}>Example</div>}
<button onClick={toggle}>Toggle</button>
<pre>{JSON.stringify(elementRect, null, 2)}</pre>
</>
);
};
- React Docs 의 다른 예를 참조해 주세요.DOM 노드를 측정하려면 어떻게 해야 하나요?
- 자세한 내용 및 더 많은 예에서는 다음 용도를 참조하십시오.
2021년 답변:
이 문서에서는 참조를 사용하는 경우의 문제에 대해 설명합니다.useEffect
: useEffect Hook 내부의 오브젝트를 참조합니다.
렌더링을 건너뛰는 useEffect와 결합하면 useRef 훅은 사용자 지정 후크의 트랩이 될 수 있습니다.첫 번째 본능은 useEffect의 두 번째 인수에 ref.current를 추가하는 것입니다.그러면 ref가 변경되면 갱신됩니다.단, 참조는 컴포넌트가 렌더링될 때까지 갱신되지 않습니다.즉, 렌더링을 건너뛰는 useEffect는 다음 렌더 패스 전에 참조에 대한 변경을 볼 수 없습니다.
또한 이 문서에서 설명한 바와 같이 공식 반응 문서는 권장 접근법(Ref + Effect 대신 콜백을 사용)으로 업데이트되었습니다.DOM 노드를 측정하는 방법을 참조하십시오.
function MeasureExample() {
const [height, setHeight] = useState(0);
const measuredRef = useCallback(node => {
if (node !== null) {
setHeight(node.getBoundingClientRect().height);
}
}, []);
return (
<>
<h1 ref={measuredRef}>Hello, world</h1>
<h2>The above header is {Math.round(height)}px tall</h2>
</>
);
}
같은 문제에 직면하여 Typescript를 사용한 커스텀 훅과 ref 콜백을 사용한 공식 접근 방식을 작성했습니다.그것이 도움이 되기를 바랍니다.
export const useRefHeightMeasure = <T extends HTMLElement>() => {
const [height, setHeight] = useState(0)
const refCallback = useCallback((node: T) => {
if (node !== null) {
setHeight(node.getBoundingClientRect().height)
}
}, [])
return { height, refCallback }
}
는 ESLint가 는는ained complainedainedainedainedainedainedainedainedained i i 、 ained 、 ained 、 、 。 에슬린트ref.current
의 사용방법useCallback
이 경고를 피하기 위해 프로젝트에 커스텀 훅을 추가했습니다.하여 변수 을 강제합니다.useCallback
참조 객체가 변경될 때마다.
import { RefObject, useCallback, useRef, useState } from "react";
/**
* This hook can be used when using ref inside useCallbacks
*
* Usage
* ```ts
* const [toggle, refCallback, myRef] = useRefWithCallback<HTMLSpanElement>();
* const onClick = useCallback(() => {
if (myRef.current) {
myRef.current.scrollIntoView({ behavior: "smooth" });
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [toggle]);
return (<span ref={refCallback} />);
```
* @returns
*/
function useRefWithCallback<T extends HTMLSpanElement | HTMLDivElement | HTMLParagraphElement>(): [
boolean,
(node: any) => void,
RefObject<T>
] {
const ref = useRef<T | null>(null);
const [toggle, setToggle] = useState(false);
const refCallback = useCallback(node => {
ref.current = node;
setToggle(val => !val);
}, []);
return [toggle, refCallback, ref];
}
export default useRefWithCallback;
되었습니다.useRef
'만들면 돼요'라고 써주세요useState
2회:1회 2회:
const [myChart, setMyChart] = useState(null)
const [el, setEl] = useState(null)
useEffect(() => {
if (!el) {
return
}
// attach to element
const myChart = echarts.init(el)
setMyChart(myChart)
return () => {
myChart.dispose()
setMyChart(null)
}
}, [el])
useEffect(() => {
if (!myChart) {
return
}
// do things with attached object
myChart.setOption(... data ...)
}, [myChart, data])
return <div key='chart' ref={setEl} style={{ width: '100%', height: 1024 }} />
차트 작성, 인증 및 기타 비반응 라이브러리에 유용합니다. 요소 참조 및 초기화된 개체를 주변에 유지하고 필요에 따라 직접 폐기할 수 있기 때문입니다.
그런지useRef
초에에 존재 ?? ???
언급URL : https://stackoverflow.com/questions/60476155/is-it-safe-to-use-ref-current-as-useeffects-dependency-when-ref-points-to-a-dom
'programing' 카테고리의 다른 글
WPML 및 커스텀 포스트 타입 아카이브 템플릿 (0) | 2023.03.12 |
---|---|
뷰포트 크기에 따라 조건부로 렌더링합니다. (0) | 2023.03.12 |
장고와 리액트 입수하는 방법JS가 같이 일한다고? (0) | 2023.03.12 |
JSON 피드에서 선택한 드롭다운 목록을 AngularJS로 채우려면 어떻게 해야 합니까? (0) | 2023.03.07 |
Javascript에는 필수 vs .default가 필요합니다. (0) | 2023.03.07 |