这个问题需要一些背景知识才能理解:
我的应用使用用户通过点击切换的布尔状态的各种项目列表。
我用两个可重用的元素实现了这个逻辑:
useSelections()
,它维护一个 { id, name, isSelected }
形式的对象数组,其中 isSelected
是布尔值并且是唯一的可变元素。它将数组作为当前状态返回,并返回一个调度函数,该函数接受 { id, newValue }
形式的输入并使用给定的 isSelected
id
成员
Selector
,它将单个项目和来自 useSelections
的分派作为 props,并返回一个 <li>
元素,其 CSS 类依赖于 isSelected
。立>
通常情况下,它们按以下方式一起使用,效果很好(即内部状态和列表项的颜色是同步的,并在单击时切换):
function localComponent(props) {
const [items, dispatch] = useSelections(props.data);
return (
<ul>
{items.map(item => <Selector key={item.id} item={item} onChange={dispatch} />)}
</ul>
);
}
当 useSelections()
被提升为父组件并且 items
和 dispatch
作为 props 传递时,它同样有效。
当数组变大时麻烦就开始了,我决定分页:
<ul>
{items.slice(start, end).map(item => <Selector key={item.id} item={item} onChange={dispatch} />)}
</ul>
(start
和 end
是组件状态的一部分。)
当我的组件第一次被渲染时,它可以正常工作。但是,一旦 start
和 end
被更改(移动到下一页),点击一个项目会改变内部状态,但不再触发重新渲染。在 UX 术语中,这意味着在第一次“下一个”点击之后,当我点击一个项目时,似乎什么也没有发生,但是如果我再次点击“下一个”,然后“返回”,我刚刚点击的项目现在已经改变了。
如有任何建议,我们将不胜感激。
答案 0 :(得分:0)
我通过从 reducer 函数中删除逻辑来忽略没有变化的调用来解决这个问题:
const hasChanged = modifiedItem.isSelected !== newValue;
modifiedItem.isSelected = newValue;
return hasChanged ? { data } : state;
现在只是:
modifiedItem.isSelected = newValue;
return { data };
这里的 React 仍有一些我不明白的地方,但我眼前的问题已经解决了。