无法重写标题,因为标题已经很明确和清晰了
P粉253518620
2023-08-15 18:38:17
<p>我正在使用React Native中的Flashlist,并且在我的<code>renderItem</code>函数中使用了<code>useCallback</code> hook。在我的组件中,我有一个状态(一个数组)叫做<code>todos</code>,当我记录<code>todos.length</code>时,我只得到初始状态值0。为什么会这样,我该如何修复?</p>
<pre class="brush:php;toolbar:false;">export default function MyComponent() {
// 为了简洁起见,省略了一些代码。
const [todos, setTodos] = useState<string[]>([]);
const renderItem = useCallback(
({ item }: ListRenderItemInfo<Todo>) => (
<TouchableOpacity
style={{ height: 50 }}
onPress={() => {
console.log(todos.length); // 总是记录0。
if (todos.length >= 10) return;
setTodos((curr) => [item.name, ...curr]);
}}
>
<Heading color={"black"}>{item.name}</Heading>
</TouchableOpacity>
),
[]
);
return (
<FlashList<Todo>
data={data?.todos as Todo[]}
estimatedItemSize={50}
renderItem={renderItem}
keyExtractor={(_, idx) => idx.toString()}
/>
);
}</pre>
<p>注意:我尝试将<code>todos</code>和<code>todos.length</code>都作为依赖项传递给<code>useCallback</code>,但结果是相同的。</p>
<p>乐意解答任何问题。</p>
和
这是一个常见的问题,因为它不明显。因为这种情况经常发生,所以
setState
有一个回调版本。在你的代码中,你实际上是使用它来设置状态,但你还需要使用它来获取当前状态以进行最大10个的检查。所以一个简单的解决方法是将长度检查放在useState的回调函数中。
在上面的代码中,如果当前长度大于或等于10,只返回当前状态,否则添加新项目。
另一个选项,当然是将todos添加到useCallback的状态中,但为什么这在
FlashList
中不起作用,不确定。更好的选择是将
Item
提取为另一个子组件。这样做还有其他好处,比如更多的组合性、代码共享,最重要的是性能。