I am trying to make a screen where users can edit recipes and one component is allowing users to edit the ingredients needed for the recipe.
Here, I have the text input component which is a custom component and a trash icon that allows users to delete that ingredient.
<View style={styles.listLabelContainer}>
<BoldedText style={styles.labelText}>Ingredients</BoldedText>
<TouchableOpacity
activeOpacity={0.5}
onPress={() => {
addListItemHandler(ingredients);
}}
>
<Ionicons
name={Platform.OS === "android" ? "md-add" : "ios-add"}
size={23}
color={Colours.primary}
/>
</TouchableOpacity>
</View>
<View>
{ingredients.map((ingredient, index) => (
<ListItem key={index}>
<View style={styles.ingredientInputContainer}>
<View style={styles.ingredientInput}>
<Input
autoCorrect
keyboardType="default"
returnKeyType="done"
required
identifier="recipeIngredient"
initialValue={ingredient}
onInputChange={() => {}}
/>
</View>
<TouchableOpacity
style={styles.deleteButton}
activeOpacity={0.5}
onPress={() => {
deleteListItemHandler(ingredients, index);
}}
>
<Ionicons
name={
Platform.OS === "android" ? "md-trash" : "ios-trash"
}
size={23}
color={Colours.primary}
/>
</TouchableOpacity>
</View>
</ListItem>
))}
</View>
</View>
The functions to delete and add an ingredient are as follows:
const [ingredients, setIngredients] = useState(
currentRecipe ? [...currentRecipe.ingredients] : []
);
const addListItemHandler = (arr) => {
// add one empty string to end of array STEP
setIngredients(arr.concat(""));
};
const deleteListItemHandler = (arr, index) => {
// remove desired index ingredient STEP
arr.splice(index, 1);
setIngredients([...arr]);
};
However, in the case where I have 5 ingredients and I choose to delete the 3rd ingredient, of array index 2, the array is updated accordingly. However, what is rendered is incorrect as the ingredient removed is the last ingredient and the ingredient to be removed is still present. My guess is that the value of the text input cannot be updated dynamically. However, is there a way to make this part of the code re-render whenever my ingredients array change so that the ingredients array is always the most updated one? This would allow for the correct rendering of ingredients.
Edit: I realise the issue is because the initialValue prop of the custom Input component is not updating whenever the array changes. Hence, what is displayed on the screen remains the same which causes the above error.
Thank you for the help.
CodePudding user response:
What I can see is that you are mutating the state and it looks like your state is not synced with the UI.
try something like this
const deleteListItemHandler = (arr, index) => {
// remove desired index ingredient STEP
const state = [...ingredients]
state.splice(index, 1);
setIngredients([...state]);
};
or
const deleteListItemHandler = (arr, index) => {
// remove desired index ingredient STEP
setIngredients( oldState => [...oldState.splice(index, 1)]);
};
CodePudding user response:
You don't need to pass the array again
const deleteListItemHandler = (index) => {
ingredients.splice(index, 1);
setIngredients([...ingredients]);
};