【问题标题】:react-window and detecting changes in size of list itemsreact-window 并检测列表项大小的变化
【发布时间】:2021-02-03 17:19:34
【问题描述】:

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

我有一个想要快速渲染的卡片列表 - 我正在使用 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.

我的第一个想法是愚蠢的......我不太确定如何解决这个问题......我很确定我不应该为每个材料卡阵列都需要一个巨大的额外阵列(有一些类别)来跟踪哪些卡片是打开的......但我似乎无法找到正确的方法。

我该如何做到这一点?

【问题讨论】:

    标签: javascript reactjs list resize react-window


    【解决方案1】:

    对于这个问题:

    我的麻烦是我不知道如何读取组件的内部状态 从上到下

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

    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),或者当活动卡的状态发生变化时您可能想要使用的任何默认参数。

    【讨论】:

    • 多张卡应该可以同时打开....但我认为这只是一个useEffect更改,让设置的活动卡成为一个函数,而不是仅仅传递密钥,好吧。 ..换句话说...您是说为每个列表创建一个 UseState 数组...以跟踪每张卡的布尔值?我理解正确吗?所以对于 2000 个项目的四个列表...我需要在顶层的 useState 中添加 4 个额外的数组来跟踪每张卡的单个布尔值...将其作为道具传递到卡中...此时我还不如使用 redux 在幕后工作?
    • 你也可以使用数组结构: const [activeCards, useActiveCards] = useState([]) 然后,确定什么是打开的,甚至是一个集合,所以, const activeSet = new Set() [activeCards, useActiveCards] = useState(activeSet) 然后检查卡片是否在集合中 activeSet.has(key) 等,并且由于 Set 具有删除、添加、清除功能,比使用 indexOf、slice 进行数组操作要容易一些, 或过滤器等。
    • set 是一个有趣的想法。但是如果所有的键都是唯一的......有什么好处吗?从集合中删除东西比从数组中删除更容易吗? - 无论如何,这一切都必须是不可变的?
    • 对,Set 只是一个额外的保护,防止重复键(就像你说的那样,无论如何这都是一种不好的做法!)
    • 我认为您不需要 redux,如果您正在设置 activeCards 并将其传递给“Row”组件,您可以检查是否处于活动状态并将其传递回包含组件(或在孩子中设置大小)......我看了一下react-window,看起来你通过可以设置从父级传递所有内容的大小,我自己没有使用它,所以不确定任何副作用,但如有疑问,请提升状态:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-28
    • 2022-09-27
    相关资源
    最近更新 更多