React: can't type accents or set the cursor in the middle of a word when using redux or dexie.js

53 Views Asked by At

If the input of a field must be equal to a global state, I usually do something like this (here in dexie.js, but I have similar issues with redux as well):

export const Friend = memo(({id}) => {
    const friend = useLiveQuery(() =>
        db.friends.get(id)
    );
    const deleteFriend = useCallback(() => db.friends.delete(id), [id]);
    const changeName = useCallback((e) => db.friends.update(id, {name: e.target.value}), [id]);
    return <>Name: {friend?.name}, Age: {friend?.age} <input value={friend?.name} onChange={changeName} /> <button onClick={deleteFriend}>Delete</button></>
})

The problem is that with this:

  1. I can't type accents that need two key presses (dead key), like ï
  2. even more annoying, I can't type something in the middle of the word, as the cursor is automatically pushed at the very end:

Here is an example where I moved my cursor to Th*is is a test (* being the position of the cursor) and typed ab ï:

enter image description here

This seems to be related to the fact that react does not handle async updates… but then what would be the recommended way to solve this issue?

MWE

You can find a simple working example here https://github.com/tobiasBora/bug-dexie.

1

There are 1 best solutions below

5
Ricola On

Both issues are cause by the same root cause, which is that the cursor will jump to the end on any change.

This is not related to Dexie, nor Redux. You have a controlled input, which means that the value of the input is set from outside the input. It makes sense that the cursor jumps to the end, what if the text changes completely? It wouldn't make sense to keep the same cursor location.

There are several workaround in the answers of React controlled input cursor jumps

Some notes

  1. No need to use async callbacks in useLiveQuery, it's not used in the documentation.
  2. No need to use useCallback if you pass that closure to a host element (, , etc). Host elements won't memoize the callbacks. You are actually slightly hurting the performance by doing so. You can read this for more details