Как заставить ререндериться страницу react native

Есть страница, на которой я пишу To Do List

export default function func() {
  const [todos, setTodos] = useState([
    {id: 1, task: "First", completed: true},
    {id: 2, task: "Second", completed: false}
  ])  
  useEffect(()=>{
    saveTodo(todos);
  },[todos]);

Сам же список тудушек задан следующим фрагментом:

const ListItem = ({todo}) => {
return <View style={styles.listenItem}>
  <View style={{flex: 1}}>
    <Text style = {{
      fontWeight: 'bold',
      fontSize: 15,
      color: '#1f145c',
      textDecorationLine: todo.completed ? 'line-through' : 'none',
    }}>
      {todo.task}
    </Text>
  </View>

  {!todo?.completed && (
    <TouchableOpacity style={[styles.actionIcon]} onPress={()=>setStatus(todo.id)}>
      <Icon name="check" size={20} color={'#fff'}/>
    </TouchableOpacity>
  )}
  <TouchableOpacity style={[styles.actionIcon, {backgroundColor: 'red'}]} onPress={() => deleteTodo(todo?.id)}>
    <Icon name="trash-o" size={20} color={'#fff'}/>
  </TouchableOpacity>


</View>}

И внутри return

<FlatList
  showsVerticalScrollIndicator={false}
    contentContainerStyle={{padding: 20, paddingBottom: 100}}
    data={todos}
    renderItem={ ({item}) => <ListItem todo={item} />}
/>

Я хочу, чтобы при вызове функции setStatus менялась отрисовка элементов списка, что и происходит, когда вызывается другая функция, при которой ререндерится весь компонент, но сама функция setStatus почему-то этого не делает.

const setStatus = (todoId) =>{
  var newTodo = todos;
  newTodo.forEach(element => {
    if(element.id == todoId) {element.completed = true; console.log("success")}
  });
  setTodos(newTodo);}

Как я понял, useState не видит изменения параметра completed, может есть какой-нибудь другой способ запустить ререндер?


Ответы (1 шт):

Автор решения: ksa

Как я понял, useState не видит изменения параметра completed, может есть какой-нибудь другой способ запустить ререндер?

Просто поменять "где-то" значение ключа не достаточно для вызова рендера... Нужно получить новую ссылку на массив и новую ссылку на измененный объект.

Пробуй сделать вот так

const setStatus = (todoId) => {
  var newTodo = todos.map(element => {
    if (element.id == todoId) {
      console.log("success")
      element = {...element, completed: true}
    }
    return element
  });
  setTodos(newTodo);
}
→ Ссылка