User G Amsterdam
User G Amsterdam

Reputation: 67

TextInput field retrieving undefined and not showing the value on the list screen

I am trying to add some new items on a list but when i print the list on console log it adds the item but it shows me undefined of name and description. Apparantly there is something wrong with the inputs but I cannot figure out why. Also on the app itself the it shows that a new item is added but without data.

import React ,{useState}from 'react';
import { KeyboardAvoidingView, StyleSheet,Text,View,TextInput,TouchableOpacity,Keyboard,ScrollView } from 'react-native';
import Task from './components/task';


export default function App(){


  
      const [recipeName,setRecipeName]=useState("");
      const [descriptionItem, setDescriptionItem] = useState("");
      const [items, setItems] = useState([
        { itemName: "Chicken", description: "chicken test", id: 0 }
      ]);
    
  

  

  const handleAddButtonClick = () => {
    
    const newItem = {
      itemName: recipeName, // change
      descriptionItem: descriptionItem,
      id: items.length
    };
    console.log(newItem);
    const newItems = [...items, newItem];

    setItems((state) => {
      console.log(state);
      console.log(newItems);
      return newItems;
    });
    // setRecipeName("");
    // setDescriptionItem("");
    // console.log(items.description);
    // console.log(items.id); //...
  };


 

  return(
    <View style={styles.container}>
    {/* Added this scroll view to enable scrolling when list gets longer than the page */}
    <ScrollView
      contentContainerStyle={{
        flexGrow: 1
      }}
      keyboardShouldPersistTaps='handled'
    >

    {/* Today's Tasks */}
    <View style={styles.tasksWrapper}>
      <Text style={styles.sectionTitle}>Today's tasks</Text>
      <View style={styles.items}>
        {/* This is where the tasks will go! */}
        {
          items.map((item, index) => {
            return (
              <TouchableOpacity key={index}  onPress={() => completeTask(index)}>
                <Text>Recipe {item.itemName}  Description: {item.description}</Text>
                
              </TouchableOpacity>
            )
          })
        }
      </View>
    </View>
      
    </ScrollView>

    {/* Write a task */}
    {/* Uses a keyboard avoiding view which ensures the keyboard does not cover the items on screen */}
    <KeyboardAvoidingView 
      behavior={Platform.OS === "ios" ? "padding" : "height"}
      style={styles.writeTaskWrapper}
    >

<View style={{flexDirection: 'column', flex: 1,  justifyContent: 'center', alignItems: 'center'}}>
      <TextInput style={styles.input} placeholder={'Write a name'} value={recipeName} onChangeText={(text) => setRecipeName(text)} />
      <TextInput style={styles.input} placeholder={'Write a date'} value={descriptionItem} onChange={(text) => setDescriptionItem(text)} />

  </View>


    
      <TouchableOpacity onPress={() => handleAddButtonClick()}>
        <View style={styles.addWrapper}>
          <Text style={styles.addText}>+</Text>
        </View>
      </TouchableOpacity>
    </KeyboardAvoidingView>
    
  </View>
  )
}


const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#E8EAED',
  },
  tasksWrapper: {
    paddingTop: 80,
    paddingHorizontal: 20,
  },
  sectionTitle: {
    fontSize: 24,
    fontWeight: 'bold'
  },
  items: {
    marginTop: 30,
  },
  writeTaskWrapper: {
    position: 'absolute',
    bottom: 60,
    width: '100%',
    flexDirection: 'row',
    justifyContent: 'space-around',
    alignItems: 'center'
  },
  input: {
    paddingVertical: 15,
    paddingHorizontal: 15,
    backgroundColor: '#FFF',
    borderRadius: 60,
    borderColor: '#C0C0C0',
    borderWidth: 1,
    width: 250,
  },
  addWrapper: {
    width: 60,
    height: 60,
    backgroundColor: '#FFF',
    borderRadius: 60,
    justifyContent: 'center',
    alignItems: 'center',
    borderColor: '#C0C0C0',
    borderWidth: 1,
  },
  addText: {},
});

Upvotes: 0

Views: 88

Answers (1)

AhmCho
AhmCho

Reputation: 390

When iterating over items in your map() function here:

items.map((item, index) => {
              return (
                <TouchableOpacity
                  key={index}
                  onPress={() => completeTask(index)}
                >
                  <Text>
                    Recipe {item.itemName} Description: {item.description}
                  </Text>
                </TouchableOpacity>
              );
            })

You are not using the correct state value. Instead of item.description, it should be item.descriptionItem.

I also advise you to move onChange events to separate methods and set the state inside them, do not use anonymous functions. So, for example, for your description, it would be something like this:

const handleDescription = (e) => { 
    setDescriptionItem(e.target.value);
};

And in your JSX:

<TextInput
        style={styles.input}
        placeholder={"Write a date"}
        value={descriptionItem}
        onChange={handleDescription}
/>

UPDATE:

I recreated your code in sandbox, with minor changes:

  • commented out the import of Task component (since I don't know what that component does)
  • disabled onPress event handler as I don't have access to completeTask function
  • changed the onChangeText for recipeName to onChange
  • extracted both onChange events to separated methods.
  • fixed initial state for items; it also had description , instead of descriptionItem

Please, feel free to check it out.

Upvotes: 1

Related Questions