我正在使用useLayoutEffect构建Carousel组件。此useLayoutEffect挂钩已在resizeWindow.ts
中单独设置。在名为carousel
的功能组件中调用resizeWindow函数。我找不到违反规则的地方。
//resizeWindow.ts
import { useLayoutEffect, useState, RefObject } from 'react'
/***
* @function resizeWindow
* this function is custom hook for grab resizing innerWidth of element.
*
*
*/
export const resizeWindow: (ref: RefObject<HTMLElement>) => number[] = (ref) => {
const [ elementWidth, elementHeight ] = ref.current ?
[ref.current.offsetWidth, ref.current.offsetHeight ] :
[0,0];
const [size, setSize] = useState([elementWidth, elementHeight]);
useLayoutEffect(() => {
const updateSize = () => {
setSize([elementWidth, elementHeight]);
console.log(`elementWidth: ${elementWidth}px`);
};
updateSize();
window.addEventListener('resize', updateSize);
return () => window.removeEventListener('resize', updateSize);
},[]);
return size;
};
//carousel.ts
//
import { resizeWindow } from './resizeWindow.ts';
export const Carousel: FC = ({
children
}) => {
const parentRef = useRef<HTMLDivElement>(null);
const slideRef = createRef<HTMLDivElement>();
const [count, setCount ] = useState<number>(0);
const [parentWidth, setParentWidth] = resizeWindow(parentRef);
const total = React.Children.count(children);
const nextSlide = () => {
if( count < total -1 ){
setCount( count + 1 );
} else if( count === total-1 ){
setCount(1);
}
}
const prevSlide = () => {
if( count > 0 ){
setCount( count -1 );
} else if( count === 0 ){
setCount(total -1 );
}
}
useEffect(()=> {
console.log('parentRef: ', parentRef);
if(slideRef.current){
slideRef.current.style.transition = "all 0.5s ease-in-out";
slideRef.current.style.transform = `translateX(-${count}00%)`;
}
if(parentRef.current){
resizeWindow(parentRef);
}
},[count || parentWidth])
return(
<SliderContainer ref={parentRef}>
<Slider ref={slideRef} width={parentWidth * total}>
{children}
</Slider>
<Indicator now={1} total={total}/>
<Button onClick={prevSlide}>left</Button>
<Button onClick={nextSlide}>right</Button>
</SliderContainer>
)
}
resizeWindow是一个自定义钩子,不应在useEffect钩子中使用它。这种用法使您出错。
此外,您还必须在自定义钩子的前面加上use
作为其名称来命名>
此外,您还必须在resizeWindow挂钩中的updateSize函数中解构ref属性,以便您不会在updateSize函数中遇到关闭问题
更新的解决方案将看起来像
export const useResizeWindow: (ref: RefObject<HTMLElement>) => number[] = (ref) => { const [size, setSize] = useState([elementWidth, elementHeight]); useLayoutEffect(() => { const updateSize = () => { const [ elementWidth, elementHeight ] = ref.current ? [ref.current.offsetWidth, ref.current.offsetHeight ] : [0,0]; setSize([elementWidth, elementHeight]); console.log(`elementWidth: ${elementWidth}px`); }; updateSize(); window.addEventListener('resize', updateSize); return () => window.removeEventListener('resize', updateSize); },[]); return size; };
及其用法如下
//carousel.ts
//
import { useResizeWindow } from './resizeWindow.ts';
export const Carousel: FC = ({
children
}) => {
const parentRef = useRef<HTMLDivElement>(null);
const slideRef = createRef<HTMLDivElement>();
const [count, setCount ] = useState<number>(0);
const [parentWidth, setParentWidth] = useResizeWindow(parentRef);
const total = React.Children.count(children);
const nextSlide = () => {
if( count < total -1 ){
setCount( count + 1 );
} else if( count === total-1 ){
setCount(1);
}
}
const prevSlide = () => {
if( count > 0 ){
setCount( count -1 );
} else if( count === 0 ){
setCount(total -1 );
}
}
useEffect(()=> {
console.log('parentRef: ', parentRef);
if(slideRef.current){
slideRef.current.style.transition = "all 0.5s ease-in-out";
slideRef.current.style.transform = `translateX(-${count}00%)`;
}
},[count || parentWidth])
return(
<SliderContainer ref={parentRef}>
<Slider ref={slideRef} width={parentWidth * total}>
{children}
</Slider>
<Indicator now={1} total={total}/>
<Button onClick={prevSlide}>left</Button>
<Button onClick={nextSlide}>right</Button>
</SliderContainer>
)
}