문서 사용.react에서 querySelector를 선택하십시오.대신 레퍼런스를 쓸까요? 어떻게요?
난 지금 리액트에 회전목마를 만들고 있어사용 중인 개별 슬라이드로 스크롤하려면document.querySelector다음과 같이 합니다.
useEffect(() => {
document.querySelector(`#slide-${activeSlide}`).scrollIntoView({
behavior: 'smooth',
block: 'nearest',
inline: 'nearest'
});
}, [activeSlide]);
이게 나쁜 관행인가요?결국, 내가 여기서 직접 DOM에 접속하는거잖아?리액트 방식으로는 어떤 것이 있을까요?
편집: 전체return방법
return (
<>
<button onClick={() => setActiveSlide(moveLeft)}>PREV</button>
<Wrapper id="test">
{children.map((child, i) => {
return (
<Slide id={`slide-${i}`} key={`slide-${i}`}>
{child}
</Slide>
);
})}
</Wrapper>
<button onClick={() => setActiveSlide(moveRight)}>NEXT</button>
</>
);
이 경우 참조를 사용할지 여부에 대해서는 답변할 수 없습니다.단, 참조는 필요 없습니다.id다른 용도로 사용하지 않는 한 가치관.
하지만 다음과 같은 방법이 있습니다.
참조를 작성하는 데 사용합니다.
const activeSlideRef = useRef(null);위에 올려놓으세요
Slide현재 활성화되어 있습니다.<Slide ref={i === activeSlide ? activeSlideRef : null} ...>고객님의 고객명
useEffect, 참조를 사용합니다.current소유물useEffect(() => { if (activeSlideRef.current) { activeSlideRef.current.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' }); } }, [activeSlide]);(내 생각에는
activeSlide그 효과에 대한 합리적인 의존관계입니다.ref는 사용할 수 없습니다. ref 자체는 달라지지 않습니다...)
실제 예에서는 일부 컴포넌트를divs 편의상:
const {useEffect, useRef, useState} = React;
function Deck({children}) {
const [activeSlide, setActiveSlide] = useState(0);
const activeSlideRef = useRef(null);
useEffect(() => {
if (activeSlideRef.current) {
activeSlideRef.current.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
inline: 'nearest'
});
}
}, [activeSlide]);
const moveLeft = Math.max(0, activeSlide - 1);
const moveRight = Math.min(children.length - 1, activeSlide + 1);
return (
<React.Fragment>
<button onClick={() => setActiveSlide(moveLeft)}>PREV</button>
<div id="test">
{children.map((child, i) => {
const active = i === activeSlide;
return (
<div className={`slide ${active ? "active" : ""}`} ref={active ? activeSlideRef : null} id={`slide-${i}`} key={`slide-${i}`}>
{child}
</div>
);
})}
</div>
<button onClick={() => setActiveSlide(moveRight)}>NEXT</button>
</React.Fragment>
);
}
ReactDOM.render(
<Deck>
<div>slide 0 </div>
<div>slide 1 </div>
<div>slide 2 </div>
<div>slide 3 </div>
<div>slide 4 </div>
<div>slide 5 </div>
<div>slide 6 </div>
<div>slide 7 </div>
<div>slide 8 </div>
<div>slide 9 </div>
</Deck>,
document.getElementById("root")
);
.slide {
height: 4em;
vertical-align: middle;
text-align: center;
}
#test {
overflow: scroll;
max-height: 20em;
}
.active {
font-weight: bold;
color: blue;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.10.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.2/umd/react-dom.production.min.js"></script>
코멘트에서 다음과 같이 질문했습니다.
디세블로 할 수 있는지 알고 계십니까?
useEffect첫 번째 렌더링을 위해 여기에 왔나요?
비상태의 컴포넌트별 정보를 유지하려면useRef문서에서는 DOM 요소 참조뿐만 아니라 컴포넌트별 비상태 데이터도 참조할 수 있다고 지적하고 있습니다.그래서 당신은
const firstRenderRef = useRef(true);
그럼 네 안에useEffect콜백, 체크firstRenderRef.currentmndash; 이 경우true설정, 설정false그렇지 않으면 스크롤을 수행합니다.
const {useEffect, useRef, useState} = React;
function Deck({children}) {
const [activeSlide, setActiveSlide] = useState(0);
const activeSlideRef = useRef(null);
// *** Use a ref with the initial value `true`
const firstRenderRef = useRef(true);
console.log("render");
useEffect(() => {
// *** After render, don't do anything, just remember we've seen the render
if (firstRenderRef.current) {
console.log("set false");
firstRenderRef.current = false;
} else if (activeSlideRef.current) {
console.log("scroll");
activeSlideRef.current.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
inline: 'nearest'
});
}
}, [activeSlide]);
const moveLeft = Math.max(0, activeSlide - 1);
const moveRight = Math.min(children.length - 1, activeSlide + 1);
return (
<React.Fragment>
<button onClick={() => setActiveSlide(moveLeft)}>PREV</button>
<div id="test">
{children.map((child, i) => {
const active = i === activeSlide;
return (
<div className={`slide ${active ? "active" : ""}`} ref={active ? activeSlideRef : null} id={`slide-${i}`} key={`slide-${i}`}>
{child}
</div>
);
})}
</div>
<button onClick={() => setActiveSlide(moveRight)}>NEXT</button>
</React.Fragment>
);
}
ReactDOM.render(
<Deck>
<div>slide 0 </div>
<div>slide 1 </div>
<div>slide 2 </div>
<div>slide 3 </div>
<div>slide 4 </div>
<div>slide 5 </div>
<div>slide 6 </div>
<div>slide 7 </div>
<div>slide 8 </div>
<div>slide 9 </div>
</Deck>,
document.getElementById("root")
);
.slide {
height: 4em;
vertical-align: middle;
text-align: center;
}
#test {
overflow: scroll;
max-height: 10em;
}
.active {
font-weight: bold;
color: blue;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.10.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.2/umd/react-dom.production.min.js"></script>
사고 실험으로 인체 공학을 좀 더 쉽게 하기 위해 후크를 썼습니다.
function useInstance(instance = {}) {
// assertion: instance && typeof instance === "object"
const ref = useRef(instance);
return ref.current;
}
사용방법:
const inst = useInstance({first: true});
인useEffect,한다면inst.first정말이야, 해inst.first = false;; 그렇지 않으면 스크롤을 수행합니다.
라이브:
const {useEffect, useRef, useState} = React;
function useInstance(instance = {}) {
// assertion: instance && typeof instance === "object"
const ref = useRef(instance);
return ref.current;
}
function Deck({children}) {
const [activeSlide, setActiveSlide] = useState(0);
const activeSlideRef = useRef(null);
const inst = useInstance({first: true});
console.log("render");
useEffect(() => {
// *** After render, don't do anything, just remember we've seen the render
if (inst.first) {
console.log("set false");
inst.first = false;
} else if (activeSlideRef.current) {
console.log("scroll");
activeSlideRef.current.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
inline: 'nearest'
});
}
}, [activeSlide]);
const moveLeft = Math.max(0, activeSlide - 1);
const moveRight = Math.min(children.length - 1, activeSlide + 1);
return (
<React.Fragment>
<button onClick={() => setActiveSlide(moveLeft)}>PREV</button>
<div id="test">
{children.map((child, i) => {
const active = i === activeSlide;
return (
<div className={`slide ${active ? "active" : ""}`} ref={active ? activeSlideRef : null} id={`slide-${i}`} key={`slide-${i}`}>
{child}
</div>
);
})}
</div>
<button onClick={() => setActiveSlide(moveRight)}>NEXT</button>
</React.Fragment>
);
}
ReactDOM.render(
<Deck>
<div>slide 0 </div>
<div>slide 1 </div>
<div>slide 2 </div>
<div>slide 3 </div>
<div>slide 4 </div>
<div>slide 5 </div>
<div>slide 6 </div>
<div>slide 7 </div>
<div>slide 8 </div>
<div>slide 9 </div>
</Deck>,
document.getElementById("root")
);
.slide {
height: 4em;
vertical-align: middle;
text-align: center;
}
#test {
overflow: scroll;
max-height: 10em;
}
.active {
font-weight: bold;
color: blue;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.10.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.2/umd/react-dom.production.min.js"></script>
수락된 답변에 더해 질문의 '해야 하는' 부분에 대한 답변을 시도하고 DOM 조작에 대한 참조를 사용하여 다음 사항을 작성합니다.
- refs를 사용하면 (여러 요소가 실수로 문서와 비교하여 + 값이 같을 수 있는 id와 비교하여) 대응하는 요소를 선형 시간에 고유하게 식별하고 선택할 수 있습니다.올바른 요소를 선택하기 위해 DOM을 스캔해야 하는 query Selector)
- ref는 react 컴포넌트의 라이프 사이클을 인식하고 있기 때문에 refact는 컴포넌트가 마운트 해제되었을 때 ref가 null로 업데이트되고 즉시 사용할 수 있는 편리성이 높아집니다.
- 개념으로서의 refs + 구문은 플랫폼에 의존하지 않기 때문에 react native와 브라우저에서 동일한 이해를 사용할 수 있으며 쿼리 실렉터는 브라우저와 같은 것입니다.
- SSR의 경우 DOM이 없는 경우에도 ref를 사용하여 react 요소를 타깃으로 할 수 있습니다.
물론 쿼리 셀렉터를 사용하는 것은 잘못된 것이 아니며 일반적으로 반응 세계에서 사용하는 경우 기능이 저하되지는 않지만 대부분의 경우 기본 이점이 있으므로 프레임워크에서 제공하는 것을 사용하는 것이 좋습니다.
언급URL : https://stackoverflow.com/questions/59198952/using-document-queryselector-in-react-should-i-use-refs-instead-how
'codememo' 카테고리의 다른 글
| mongodb가 strict JSON을 출력하도록 강제합니다. (0) | 2023.02.27 |
|---|---|
| Typescript 개체의 인덱싱된 멤버 유형을 적용하시겠습니까? (0) | 2023.02.27 |
| Python에서 숫자 목록을 jsonarray로 변환하는 방법 (0) | 2023.02.27 |
| 동일 발신기지 정책을 회피하는 방법 (0) | 2023.02.27 |
| Spring Boot 애플리케이션에서 HikariCP 및 Drop Wizard/Coda-Hale 메트릭을 구성하는 방법 (0) | 2023.02.27 |