Reputation: 353
Newbie question, I am getting a TypeError: Cannot read properties of undefined (reading 'id')
on the following code. Am I passing in props correctly? Why would this value be undefined? My getValues
button returns an empty list with a length
attribute of 0, so why is it that this is undefined when created and passed to child component?
InputScreen.js
import React, { useState } from 'react';
import { v4 as uuidv4 } from 'uuid';
import { View, StyleSheet, ScrollView, FlatList } from 'react-native';
import { Button, Caption } from 'react-native-paper';
import InputCard from '../components/InputCard';
const InputScreen = props => {
const [formState, setFormState] = useState([]);
const addInput = () => {
setFormState([
...formState,
{
id: formState.length,
substance: "",
amount: "",
measure: ""
},
]);
};
const handleInputChange = (index, newStateForIndex) => {
let newFormState = [...formState];
setFormState([
...newStateForIndex.slice(0,index),
newStateForIndex,
...newStateForIndex.slice(index+1)
]);
};
const removeLastInput = () => {
if (formState.length > 0) {
const lastindex = formState.length - 1;
setFormState(formState.filter((item, index) => index !== lastindex));
}
};
const getValues = () => {
console.log('Form State: ',formState,'Length: ',formState.length);
};
return (
<ScrollView>
<View style={styles.col}>
<View style={styles.row}>
<Caption>What substances are you checking out?</Caption>
</View>
<View style={styles.row}>
<View>
{formState.map((state, i) =>
<InputCard
key={uuidv4()}
formState={state[i]}
handleChange={handleInputChange}
/>
)}
</View>
</View>
<View>
<View style={styles.col}>
<Button title='Add' onPress={addInput}>Add</Button>
</View>
<View style={styles.col}>
<Button title='Remove' onPress={removeLastInput}>Remove</Button>
</View>
<View style={styles.col}>
<Button title='GetVals' onPress={getValues}>Get Values</Button>
</View>
</View>
</View>
</ScrollView>
);
};
export default InputScreen;
InputCard.js
import React from "react";
import { View, StyleSheet } from 'react-native';
import { Caption, Card, TextInput } from "react-native-paper";
const InputCard = ({ formState, handleChange }) => {
const id = formState.id; // <- Error occurs here
return (
<View>
<Card>
<Card.Content>
<Caption>Item {id}</Caption>
<View style={styles.row}>
<View style={styles.half}>
<TextInput
label="substance"
value={formState.substance}
onChangeText={(event) => {
handleChange(
id,
{
...formState,
substance: event.target.value
});
}} // change needs to be made from here to parent
mode="outlined"
right={<TextInput.Icon name="pill" />}
style={styles.textfield}
/>
</View>
<View style={styles.quarter}>
<TextInput
label="amount"
value={formState.amount}
onChangeText={(event) => {
handleChange(
id,
{
...formState,
substance: event.target.value
});
}}
mode="outlined"
keyboardType="number-pad"
/>
</View>
<View style={styles.quarterlast}>
<TextInput
label="measure"
value={formState.measure}
onChangeText={(event) => {
handleChange(
id,
{
...formState,
substance: event.target.value
});
}}
mode="outlined"
/>
</View>
</View>
</Card.Content>
</Card>
</View>
);
};
export default InputCard;
Upvotes: 1
Views: 84
Reputation: 1374
Your formState
represents an array containing objects, so inside the loop, your first argument is an element of that array which is an object, you don't need to use an index for it.
<View>
{formState.map((state, i) =>
<InputCard
key={uuidv4()}
formState={state} // <- pass state instead of state[i]
handleChange={handleInputChange}
/>
)}
</View>
Upvotes: 2