GeraltDieSocke
GeraltDieSocke

Reputation: 1618

How can I combine onBlur and onFocus in my React Component without reselecting the text on every letter I type in?

I have a simple text input that looks like this:

<input
    type="text"
    value={listTitle}
    onChange={handleChange}
    autoFocus
    onFocus={handleFocus}
    onBlur={handleFinishEditing}
/>

handleFocus does just this e.target.select()

onBlur does just dispatch an action. (and sets the state so it doesn't show the input anymore)

The problem is with the handleFocus I think together with onBlur it doesn't quite work good together.

Everytime I type in the textfield it is just writing one letter and reselecting that letter. So it's like on every change the onSelect runs.

When I get rid of the onFocus prop everything works as expected (simple react controlled input - where it gets the value from state, and sets the state onChange).

Why is this happening and how can I prevent it?

I tried out different e.preventDefaulton the functions but neither worked. I mean when I'm just typing in something in text field the onBlur shouldn't even run. But the onSelect does, but I just want to run this when the component (the input) gets rendered initially.

Here is an example of how it should be: https://codesandbox.io/s/7y66ykqn2q?fontsize=14

This is the repo Branch: CRUD : https://github.com/SelfDevTV/trello-clone/tree/CRUD

This is the same code I use on github but to play around with in Codesandbox: https://codesandbox.io/s/q3o7zjjjqw

Thx in advance guys!

Upvotes: 1

Views: 480

Answers (1)

GeraltDieSocke
GeraltDieSocke

Reputation: 1618

Ok guys I fixed it. The bug came from styled-components The bug was related to this part of the docs:

https://www.styled-components.com/docs/basics#coming-from-css

"Define Styled Components outside of the render method"

At first the component looked like this:

const TrelloList = ({ title, cards, listID, index, dispatch }) => {
  const [isEditing, setIsEditing] = useState(false);
  const [listTitle, setListTitle] = useState(title);



  const StyledInput = styled.input`
  width: 100%;
  border: none;
  outline-color: blue;
  border-radius: 3px;
  margin-bottom: 3px;
  padding: 5px;
`;

  const renderEditInput = () => {
    return (
      <StyledInput
        type="text"
        value={listTitle}
        onChange={handleChange}
        autoFocus
        onFocus={handleFocus}
        onBlur={handleFinishEditing}
      />
    );
  };

  // other stuff

Now I changed it to look like this:

const StyledInput = styled.input`
  width: 100%;
  border: none;
  outline-color: blue;
  border-radius: 3px;
  margin-bottom: 3px;
  padding: 5px;
`;

const TrelloList = ({ title, cards, listID, index, dispatch }) => {
  const [isEditing, setIsEditing] = useState(false);
  const [listTitle, setListTitle] = useState(title);



  const renderEditInput = () => {
    return (
      <StyledInput
        type="text"
        value={listTitle}
        onChange={handleChange}
        autoFocus
        onFocus={handleFocus}
        onBlur={handleFinishEditing}
      />
    );
  };

  // other stuff

This fixes the problem completely and thefore the node doesn't get deleted on every rerender. So this was my fault and I should have read the styled-components docs more in depth.

Upvotes: 1

Related Questions