Почему не обновляется компонент после изменения состояния?
Почему же не обновляется компонент после изменения состояния?
Я пытался изменять его разными способами и это работало, но FlatList не хочет заново рендерить компоненты:
import React, { useEffect, useState } from 'react'
import { FlatList,KeyboardAvoidingView, StyleSheet, Text, TouchableOpacity, View, TextInput } from 'react-native'
import { AntDesign } from '@expo/vector-icons'
import colors from '../utils/colors';
import { TodoListScreenRouteProp } from '../routes/AppNavigator'
import { ListType, TodoType } from '../redux/types'
type Props = {
route: TodoListScreenRouteProp,
}
const TodoListScreen: React.FC<Props> = ({route}) => {
const [list, setList] = useState<ListType>(route.params.list)
useEffect(() => {
// Once when component renders
console.log('updated');
}, [list])
const toggleComplete = (idx: number) => {
setList((prev) => {
const newList = prev
newList.todos[idx].completed = !newList.todos[idx].completed
return newList
})
}
const renderTodoItem = (todo: TodoType, idx: number) => {
return (
<View style={styles.todoContainer}>
<TouchableOpacity onPress={() => toggleComplete(idx)}>
<AntDesign
name={todo.completed ? 'checksquare' : 'checksquareo'}
size={24}
color={todo.completed ? list.color : colors.gray}
style={{ width: 32, marginRight: 6 }}
/>
</TouchableOpacity>
<Text style={{
textDecorationLine: todo.completed ? 'line-through' : 'none',
color: todo.completed ? list.color : colors.gray
}}>
{todo.title}
</Text>
</View>
)
}
const taskCount = list.todos.length;
const completedCount = list.todos.filter(todo => todo.completed).length;
return (
<KeyboardAvoidingView behavior='padding' style={styles.container}>
<View style={[styles.section, styles.header, {borderBottomColor: list.color}]}>
<Text style={styles.title}>
{list.name}
</Text>
<Text style={styles.taskCount}>
{completedCount} of {taskCount}
</Text>
</View>
<View style={[styles.section, {flex: 8}]}>
<FlatList
data={list.todos}
renderItem={({ item, index }) => renderTodoItem(item, index)}
keyExtractor={(_, idx) => idx.toString()}
contentContainerStyle={{paddingHorizontal:32, paddingVertical: 64}}
showsHorizontalScrollIndicator={false}
/>
</View>
</KeyboardAvoidingView>
)
}
Ответы (1 шт):
Автор решения: nörbörnën
→ Ссылка
Потому что state не меняется, т.е. в state остаётся ссылка на прежний массив.
Чтобы state обновился, нужно вернуть новый массив:
const toggleComplete = (idx: number) => {
setList((prev) => {
const newList = [ ...prev ]
newList.todos[idx].completed = !newList.todos[idx].completed
return newList
})
}