我正在使用https://www.npmjs.com/package/react-slick,并且尝试根据可用宽度动态地将其设置为“ slidesToShow”。
我设法使其正常运行,但仅在调整窗口大小之后才可以。我需要提供一个根据元素宽度计算出的初始状态。问题在于该元素当时不存在。
这是我的代码(有趣的部分):
const Carousel = (props: ICarouselProps) => {
const slider = useRef(null);
const recalculateItemsShown = () => {
const maxItems = Math.round(
slider.current.innerSlider.list.parentElement.clientWidth / 136, // content width is just hardcoded for now.
);
updateSettings({...props.settings, slidesToShow: maxItems});
};
useEffect(() => {
window.addEventListener('resize', recalculateItemsShown);
return () => {
window.removeEventListener('resize', recalculateItemsShown);
};
});
const [settings, updateSettings] = useState({
...props.settings,
slidesToShow: //How do I set this properly? slider is null here
});
return (
<div id="carousel" className="carousel">
<Slider {...settings} {...arrows} ref={slider}>
<div className="test-content/>
<div className="test-content/>
/* etc. */
<div className="test-content/>
<div className="test-content/>
<div className="test-content/>
</Slider>
</div>
);
};
export default Carousel;
如果我在updateSettings
中调用useEffect
,则会遇到无限循环。
所以我必须:
答案 0 :(得分:1)
您可以有一个返回maxItems
并可以在各处使用的函数,所以:
const getMaxItems = () => Math.round(slider.current.innerSlider.list.parentElement.clientWidth / 136)
您可以在recalculateItemsShown
中使用其返回结果来更新设置。
const recalculateItemsShown = () => {
updateSettings({...props.settings, slidesToShow: getMaxItems()});
};
您还可以使用其返回值初始设置状态。
const [settings, updateSettings] = useState({
...props.settings,
slidesToShow: getMaxItems()
});
如果元素最初不存在,则可以将useEffect
与空数组一起用作第二个参数。这告诉useEffect
监视对该数组的更改,并在每次更改时调用它,但是由于它是一个永远不会更改的空数组,因此只会在一次渲染时运行一次。
useEffect(() => {
updateSettings({...props.settings, slidesToShow: getMaxItems()});
}, []);
您可以在此处了解有关跳过应用事件的更多信息:https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects
答案 1 :(得分:1)
我相信uselayouteffect
挂钩是针对这种确切的用例而设计的。
https://reactjs.org/docs/hooks-reference.html#uselayouteffect
它的功能与useEffect完全相同,除了它会在dom加载后触发,以便您可以根据需要计算元素宽度。