简体   繁体   English

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

[英]react-window and detecting changes in size of list items

So I have been trying to figure out a solution for big lists in react.所以我一直在试图找出一个反应大列表的解决方案。 and I almost have the perfect solution - but I can't seem to figure out how to get this one detail to work.我几乎有了完美的解决方案——但我似乎无法弄清楚如何让这个细节发挥作用。

I have a list of cards that I want to render quickly - I'm using the react-window package我有一个我想快速渲染的卡片列表 - 我正在使用 react-window package

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

I have a component called MaterialCard, and a component that contains lists of MaterialCards:我有一个名为 MaterialCard 的组件,以及一个包含 MaterialCard 列表的组件:

On the MaterialCard if you click on an inspect button - it opens up the innards of the card revealing a form input section.在 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>}

In the multi-list component container - I have this code.在多列表组件容器中 - 我有这个代码。

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>

Currently the itemSize is what I'm trying to fix...目前 itemSize 是我正在尝试修复的...

What happens currently is the item has a fixed size area it appears in - and (thanks to z-index) the innards appear over other items in the list.当前发生的情况是该项目有一个固定大小的区域,它出现在 - 并且(感谢 z-index)内脏出现在列表中的其他项目之上。

What I want to happen is the item size of the MaterialCard that is open - to be of a larger size: such that it doesn't cover other cards - I want it to expand and I don't want it to cover other cards at all.我想要发生的是打开的 MaterialCard 的项目大小 - 尺寸更大:这样它不会覆盖其他卡片 - 我希望它扩展并且我不希望它覆盖其他卡片全部。

My trouble is I don't know how to read the component's internal state from the top - how do I determine in the list container component which card is open.我的麻烦是我不知道如何从顶部读取组件的内部 state - 如何在列表容器组件中确定打开的卡。 I understand I require a function for this... but: well...我知道我需要一个 function 来做这个......但是:嗯......

the pseudocode I've come up with is this: this of course does not work - but it is more or less what I want to do.我想出的伪代码是这样的:这当然是行不通的——但这或多或少是我想做的。


//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.

My first ideas are bunk... and I'm not really sure how to approach this... I'm pretty sure I shouldn't need a massive additional array for each array of material cards (there are a few categories) to keep track of which cards are open... but I can't seem to find the correct way of going about this.我的第一个想法是愚蠢的......我不太确定如何解决这个问题......我很确定我不应该为每个材料卡阵列(有几个类别)都需要一个巨大的额外阵列来跟踪哪些卡是打开的......但我似乎无法找到正确的方法来解决这个问题。

How do I accomplish this?我该如何做到这一点?

For this issue:对于这个问题:

My trouble is I don't know how to read the component's internal state from the top我的麻烦是我不知道如何从顶部读取组件的内部 state

Lift state up.向上提起 state。 So in the containing component, you can use a hook like in the top level component:因此,在包含组件中,您可以使用顶级组件中的钩子:

const [activeCard, setActiveCard] = useState()

And in the card, pass in the function:并在卡片中,传入 function:

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

And, in the implementation of the card, you can have something like:而且,在卡片的实现中,你可以有类似的东西:

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

And the top level component will have the 'active' card information.顶级组件将具有“活动”卡信息。

Not sure I completely was clear on the issue, but that is one mechanism for sending child information to the parent.不确定我是否完全清楚这个问题,但这是将子信息发送给父母的一种机制。

And, if I am understanding the issue, you could have some logic in the child component to check if the active card is equal to the card:而且,如果我理解这个问题,你可以在子组件中有一些逻辑来检查活动卡是否等于卡:

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

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

Of course, the setComponentSize would be in the top level component, and passed in a similar fashion to setting the card index in the top level.当然,setComponentSize 将位于顶层组件中,并以类似的方式传递给在顶层设置卡片索引。 And if everything is set in the containing (parent component), you could just check the index vs the activeCard .如果所有内容都设置在包含(父组件)中,您只需检查indexactiveCard

Finally, just make sure however you are checking for the active card, you cleanup and call setActiveCard(-1), or whatever the default parameter you might want to use when the active card's state changes.最后,只要确保您正在检查活动卡、清理并调用 setActiveCard(-1),或者当活动卡的 state 更改时您可能想要使用的任何默认参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM