Почему не обновляется компонент после изменения состояния?

Почему же не обновляется компонент после изменения состояния?

Я пытался изменять его разными способами и это работало, но 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
    })
}
→ Ссылка