0

I'm stuck with this for several days, I've gone through React.js - input losing focus when rerendering which lists several suggestions and solutions to losing focus on first keystroke - but I still haven't managed to solve it. I'm panic-stricken at this point so probably missed the obvious solution.

  • "Other" TextEditor always loses focus after first key stroke
  • "Resources" TextEditors loses focus if there are more than 1 resources. So, something must be right for it to keep focus with just one TextEditor...

Here's a codesandbox showing the focus loss: https://codesandbox.io/s/fervent-tereshkova-bz1wz?file=/agenda.js

Cookie
  • 364
  • 1
  • 2
  • 12
  • 1
    Can you create a minimum reproducible example in codesandbox or similar? Its difficult to tell anything just from your example-code. Often you will find the error if you remove all unnecessary code. Is there anything special going in in the ` `-component? How do you update the text in the form? – christianeide Dec 01 '21 at 17:53
  • I just tried to produce a codesandbox, frustratingly enough it works in that context: https://codesandbox.io/s/fervent-tereshkova-bz1wz?file=/agenda.js On my local, if I switch out the to a I still have the same problem :/ so it's not there – Cookie Dec 02 '21 at 12:01
  • 1
    This usually means that the entire form is recreated on each keystroke. In your codesandbox the forms are not rerendered on keypress, meaning the data in the form is not controled by react. Is your setup the same in your local? Is the codesandbox-example wrapped in another component that might be recreated on each keystroke? – christianeide Dec 02 '21 at 12:32
  • To start: I'm extremely grateful you're trying to help me. I've been at it for another 3h today. SO, now that I tried again with the instead of it indeed does work locally. I can't get the TextEditor to work in the sandbox either, I've added the slate dependencies... https://codesandbox.io/s/fervent-tereshkova-bz1wz?file=/TextEditor.js I'm at a loss. I've spent more time on this bug than all the features combined. – Cookie Dec 02 '21 at 13:54
  • I GOT THE CODESANDBOX TO WORK!!! OK, so now you'll see that after first keystroke in any of the texteditors loses focus – Cookie Dec 02 '21 at 14:01
  • Also, to answer your question, no the entire form is not recreated on each keystroke! – Cookie Dec 02 '21 at 14:39
  • I can now see that the first keystroke actually dont remove the focus, it only moves it from the first to the laste textbox in the list. This is indicating that it has something todo with the element order or the keys. Will see if I can take a closer look at this later – christianeide Dec 02 '21 at 15:41
  • @Martin that is the bug I am trying to solve! – Cookie Dec 02 '21 at 16:44
  • @christianeide thank you again. I've thought about the ordering, but believe the last TextEditor that isn't mapped shouldn't lose focus... keystroking the last one first, focus will not shift but just be lost. – Cookie Dec 02 '21 at 16:44

1 Answers1

2
onChange = ({ value }) => {
    if (this.props.onChange) {
      // Check to see if the document value really has changed
      if (value.document !== this.state.value.document) {
        this.props.onChange(value);  //  <----- This line is ruining it for you
      }
    }
    this.setState({ value });
  };

The indicated line is ruining it for you, I didn't understand what you need it for. If you want to trigger a callback when the state really changed you should do this via componentWillUpdate(object nextProps, object nextState) and there compare nextState.value.document with this.state.value.document like this:

componentWillUpdate = (object nextProps, object nextState) => {
  if (nextState.value.document !== this.state.value.document)
    this.props.onChange(nextState.value);
}

...or you could use the setState callback to trigger code after the state has updated:

onChange = ({ value }) => {
  var newDocValue = value.document;
  var oldDocValue = this.state.value.document;
  this.setState({ value }, () => {
    if (oldDocValue !== newDocValue)
      this.props.onChange(newDocValue);
  });
}

I personally would rewrite the whole component as a function component, as I consider the lifecycle- and change-reaction handling much easier with useEffect hooks.

Martin
  • 5,714
  • 2
  • 21
  • 41
  • Hmm first suggestion with componentWillUpdate didn't do it, will try the others! Thank you. Also agree re the rewriting to functional, which I've planned to do but isn't in this sprint. – Cookie Dec 02 '21 at 19:58