react-window 并检测列表项大小的变化

问题描述

所以我一直在尝试找出反应中大列表的解决方案。我几乎有了完美的解决方案 - 但我似乎无法弄清楚如何让这个细节发挥作用。

我有一个快速渲染的卡片列表 - 我正在使用 react-window 包

import{VariableSizeList as List} from 'react-window';

我有一个名为 MaterialCard 的组件,以及一个包含 MaterialCard 列表的组件:

在 MaterialCard 上,如果您单击检查按钮 - 它会打开卡片的内部,显示表单输入部分。

const [cardOpen,setCardOpen] = useState(false);
const cardInnards = //a bunch of jsx.

//in the return
<button className="btn-inspect" onClick={()=>setCardOpen(!cardOpen)}>inspect/edit</button>
{cardOpen?cardInnards:<div></div>}

在多列表组件容器中 - 我有这个代码

const materialCardsNew = materialsNew.map((x,i)=><MaterialCard props={x} key ={`${i}matsnew`} />);
//react-window function to make a row:
const Row = array=> ({ index }) => array[index] //is MaterialCard

//in the return
<List
  height={755}
  itemCount={materialCardsNew.length-1}
  itemSize={()=>130} // this is where I'm having trouble.
  width={634}
>
{Row(materialCardsNew)}
</List>

目前 itemSize 是我想要修复的...

当前发生的情况是该项目有一个固定大小的区域,它出现在 - 并且(感谢 z-index)内脏出现在列表中的其他项目之上。

我想要发生的是打开的 MaterialCard 的项目大小 - 具有更大的尺寸:这样它就不会覆盖其他卡片 - 我希望它扩展并且我不希望它覆盖其他卡。

我的问题是我不知道如何从顶部读取组件的内部状态 - 我如何确定列表容器组件中哪个卡是打开的。我知道我需要一个功能...但是:嗯...

我想出的伪代码是这样的:这当然行不通 - 但它或多或少是我想要做的。


//resize function
const getHeight = (arr)=>(index)=>arr[index].state.cardOpen?500:100; //bigger size if the card is open

//jsx
itemSize={getHeight(materialCardsNew)}
        
//I've also tried arr[index].style.height,//and searched through the arr[index] properties in the console to see 
//if there was anything I Could use... no luck.

我的第一个想法是胡说八道......我真的不确定如何处理这个......我很确定我不应该为每个材料卡阵列都需要一个庞大的额外阵列(有一些类别)来跟踪哪些卡是打开的......但我似乎找不到正确的方法

我该如何实现?

解决方法

对于这个问题:

我的问题是我不知道如何读取组件的内部状态 从顶部

提升状态。因此,在包含组件中,您可以像在顶级组件中一样使用钩子:

const [activeCard,setActiveCard] = useState()

并在卡片中,传入函数:

<Card setActiveCard={setActiveCard} key={someKey} {...otherProps}/>

而且,在卡片的实现中,你可以有类似的东西:

useEffect(() => setActiveCard(key),[key])

顶级组件将具有“活动”卡片信息。

不确定我是否完全清楚这个问题,但这是一种将子信息发送给父母的机制。

而且,如果我理解这个问题,你可以在子组件中有一些逻辑来检查活动卡片是否等于卡片:

<Card setActiveCard={setActiveCard} activeCard={activeCard} key={someKey} {...otherProps} />

useEffect(() => activeCard === key ? setComponentSize(activeSize) : setComponentSize(defaultSize),[{dependency array}])

当然,setComponentSize 将在顶级组件中,并以类似于在顶级设置卡片索引的方式传递。如果所有内容都在包含(父组件)中设置,您只需检查 indexactiveCard

最后,只要确保您正在检查活动卡,清理并调用 setActiveCard(-1),或者当活动卡的状态改变时您可能想要使用的任何默认参数。