To make it work you need to add new edit handler, similar to pressHandler
, but editing an entry instead of removing it. The possible edit handler could look like:
const editHandler = (todoKey, newText) => {
const newTodos = [...todos];
const index = newTodos.findIndex(todos => todos.key === todoKey);
newTodos[index] = Object.assign(newTodos[index], { value: newText });
setTodos(newTodos);
};
It moves the edited element at the end of the list. If you want, you can change this behavior on your own.
Then you need to pass the handler to <TodoItem />
:
<TodoItem
key={item.key}
todoKey={item.key}
title={item.value}
editHandler={editHandler}
pressHandler={pressHandler}
/>
You don't need to bind function component functions, but you need to provide a key
props for every component you render in map()
. I've changed it and provided a todoKey
props I later use in <TodoItem />
.
In <TodoItem />
you can similar logic for modifing todo text as you use in <AddTodo />
for creating new todo. I use conditional rendering to render the <TextInput />
when isEditing
is true
, and <Text />
when it's not.
{isEditing
? <TextInput value={text} onChangeText={setText} style={styles.itemText} />
: <Text style={styles.itemText}>{props.title}</Text>
}
Similarly, I conditionally render Save and Edit buttons.
Full <TodoItem />
component:
const TodoItem = props => {
const [text, setText] = useState("");
const [isEditing, setEdit] = useState(false);
const handleEdit = () => {
props.editHandler(props.todoKey, text);
setText("");
setEdit(false);
};
return (
<View style={styles.items}>
<View style={styles.itemContainer}>
{isEditing
? <TextInput value={text} onChangeText={setText} style={styles.itemText} />
: <Text style={styles.itemText}>{props.title}</Text>
}
<View style={styles.btnContainer}>
<Buttons title="Delete" onPress={() => props.pressHandler(props.todoKey)} style={styles.itemBtn} />
{isEditing
? <Buttons title="Save" onPress={handleEdit} style={styles.editBtn} />
: <Buttons title="Edit" onPress={() => setEdit(true)} style={styles.editBtn} />
}
</View>
</View>
</View>
);
};
const styles = /* ... */
Here is codesandbox with a code: https://codesandbox.io/s/public-edit-todo-item-bsc9p
EDIT 1
If you want to load current TODO title during edit instead of clearing it first, change <TodoItem />
:
- set
props.title
as initial value of text
- remove
setText("")
from handleEdit
- it's not needed anymore
const TodoItem = props => {
const [text, setText] = useState(props.title);
const [isEditing, setEdit] = useState(false);
const handleEdit = () => {
props.editHandler(props.todoKey, text);
setEdit(false);
};
return (
{/* stays the same */}
)
}