React组件(Viewer
)包含元素(Element
)的动态列表。元素的大小取决于当前的屏幕分辨率。
以下将屏幕分辨率配置动态传递给Viewer
组件:
<Viewer
elements={[{
uid: '1',title: 'project 1'
},{
uid: '2',title: 'project 2'
},{
uid: '3',title: 'project 3'
},{
uid: '4',title: 'project 4'
}]}
configurations={[
{
name: 'large screen',width: 1200,gridRowSize: 4
},{
name: 'tablet',width: 800,gridRowSize: 2
},{
name: 'phone',width: 480,gridRowSize: 1
}
]}/>
configurations
属性是动态的,Viewer
组件由于来自REST API,因此无法对其进行任何假设。配置和元素彼此不相关。
我正在使用react-responsive
来达到以下目的:
import {useMediaQuery} from 'react-responsive';
export default function Viewer(props) {
const configurations = [];
if (props.configurations) {
for (const [index,configuration] of props.configurations.sort((a,b) => (a.width - b.width)).entries()) {
configurations.push({
// props.configurations does not change between renders,so it's safe to disable the lint check
// eslint-disable-next-line react-hooks/rules-of-hooks
isactive: useMediaQuery({
...index > 0 && {minWidth: props.configurations[index - 1].width},...index < (props.configurations.length - 1) && {maxWidth: configuration.width}
}),size: 100 / configuration.gridRowSize
});
}
}
const activeConfiguration = configurations.find(config => config.isactive);
const size = activeConfiguration ? activeConfiguration.size : 25;
return (
<div classname={'viewer'}>
{
props.elements && props.elements.map((element) => (
<Element
key={element.uid}
id={element.uid}
title={element.title}
size={`${size}%`}/>
))
}
</div>
);
}
问题在于上面的实现违反了此处所述的Hooks规则之一:https://reactjs.org/docs/hooks-rules.html#eslint-plugin(React依赖于调用Hooks的顺序,并且循环理论上可以破坏该顺序)。
在不禁用棉绒检查的情况下,运行eslint
时出现此错误:
React Hook "useMediaQuery" may be executed more than once. Possibly because it is called in a loop.
React Hooks must be called in the exact same order in every component render react-hooks/rules-of-hooks
由于props.configurations
在渲染之间不会更改,因此我目前正在禁用棉绒错误检查,但是我想知道是否有更好的方法使用react-responsive
配置动态媒体查询?