DTek
DTek

Reputation: 371

How to remove component that is rendered from a list? React Native

I've been following this tutorial for ReactJS and have been trying now to convert the simplistic Todo App (just checks off and on items) to React Native. I've been using expo to try it live on my phone and everything.

It all went good, but now I'm trying to add something. Whenever I click the checkbox I want to remove the component related to that item.

My idea was:

Since I'm rendering the TodoItem components from an array of todos, and whenever I click a checkbox it updates the array as a whole (looking for a certain id and updating it's completed variable). I can run through the array and whenever the id is different I return the todo. This way I returned every todo but the one with matching id to be rendered.

import React, { Component }  from 'react';
import { Alert,Image,StyleSheet, Text,Button, View } from 'react-native';
import TodoItem from './TodoItem'
import todosData from "./todosData"

export default class App extends React.Component {
  constructor() {
    super()
    this.state = {
      todos: todosData
    }

    this.handleChange = this.handleChange.bind(this)

  }


  handleChange(id) {
    this.setState(prevState => {
      const updatedTodos = this.state.todos.map( todo => {
    if(todo.id !== id) {
      return todo
    }

  })
  return {
    todos:updatedTodos
  }
})
  }
  render() {

const todoItems = this.state.todos.map( item =>
  <TodoItem
    key={item.id}
    item={item}
    handleChange = {this.handleChange}
  />
)
return (
  <View style={styles.container}>

    {todoItems}

  </View>
    );
  }
}

This gives an error: ' TypeError:undefined is not an object (evaluating 'item.id')', giving at App.js:42:18

I'll also add the code referring to the TodoItem:

import React, { Component }  from 'react';
import { Alert,Image,StyleSheet, Text,Button, View } from 'react-native';
import { CheckBox } from 'react-native-elements'
function TodoItem(props) {
  return (
    <View>
    <CheckBox
      checked={props.item.completed}
      onPress={() => props.handleChange(props.item.id)}
    />
    <Text>{props.item.text}</Text>


    </View>
  );
}
export default TodoItem

I don't understand why this won't work. It feels like I'm deleting the component while still using it (for it to give a undefined), but I don't see where. Since I'm simple updating a list of todos. How can I do the thing I want?

PS: I seem unable to properly format the first segment of code. I apologize for that!

Upvotes: 0

Views: 3985

Answers (1)

Luna
Luna

Reputation: 1178

Try this:

handleChange(id) {
  const { todos } = this.state
  // filter out the deleted one
  const filtered = todos.filter(x => x.id !== id)

  this.setState({ todos: filtered })
}

We don't want to alter the state directly, but since .filter() creates a new array, without touching the given array, it is fine to use it. if it was another operation, you'd do something like this:

// create a copy
const newSomethings = [...this.state.somethings]
// do whatever with newSomethings
this.setState({ somethings: newSomethings })

Upvotes: 2

Related Questions