reactjs - Is JavaScript's .setSelectionRange() incompatible with React Hooks? - Stack Overflow

This question revamps a question on rreactjs.I have a controlled input of which I can programmatically

This question revamps a question on r/reactjs.

I have a controlled input of which I can programmatically change the value. I would like to use .setSelectionRange() in order to maintain the caret position within the input.

Except this doesn't work: each re-render automatically sets the selection range to the end of the input by default.

The problem is illustrated in this sandbox, where the author of the original question fixed the problem with a 10ms setTimeout() delay.

How do I achieve this without using setTimeout() or getSnapshotBeforeUpdate(), which is not patible with Hooks?

This question revamps a question on r/reactjs.

I have a controlled input of which I can programmatically change the value. I would like to use .setSelectionRange() in order to maintain the caret position within the input.

Except this doesn't work: each re-render automatically sets the selection range to the end of the input by default.

The problem is illustrated in this sandbox, where the author of the original question fixed the problem with a 10ms setTimeout() delay.

How do I achieve this without using setTimeout() or getSnapshotBeforeUpdate(), which is not patible with Hooks?

Share Improve this question edited Nov 21, 2022 at 8:28 sideshowbarker 88.6k30 gold badges215 silver badges212 bronze badges asked Feb 8, 2020 at 18:03 user5902649user5902649 1
  • FYI that the link to the sandbox is dead now. – Atticus29 Commented Jun 22, 2023 at 20:48
Add a ment  | 

1 Answer 1

Reset to default 4

The basic problem as I see it is that .setSelectionRange() is being used in-line in the template, and should be wrapped in a useEffect().

I would also pull the selection handler out, just to be a bit tidier (as per handleDomainChange() and handleSubmit()).

useEffect for selection update

const[selection, setSelection] = useState()

useEffect(() => {
  if (!selection) return;  // prevent running on start
  const {start, end} = selection;
  inputEl.current.focus();
  inputEl.current.setSelectionRange(start, end);
}, [selection])

const handleSelection = (e) => {
  const start = inputEl.current.selectionStart;
  const end = inputEl.current.selectionEnd;

  ... // other code within selection handler as per original

  // inputEl.current.focus();
  // // the line below doesn't work!
  // // inputEl.current.setSelectionRange(start + e.native.length, end + e.native.length)

  // //this one does, but is not good practice..
  // setTimeout(
  //   () =>
  //     inputEl.current.setSelectionRange(
  //       start + e.native.length,
  //       end + e.native.length
  //     ),
  //   10
  // );
  setSelection({start: start + e.native.length, end: end + e.native.length});
}

template change to call handleSelection()

<Picker
  set="emojione"
  onSelect={event => {
    handleSelection(event)
  }}
/>

Original code for reference

<Picker
  set="emojione"
  onSelect={e => {
    const start = inputEl.current.selectionStart;
    const end = inputEl.current.selectionEnd;
    //const result = domainString.substring(0, start) + e.native + domainString.substring(end, domainString.length)

    setDomainString(
      prevString =>
        prevString.substring(0, start) +
        e.native +
        prevString.substring(end, prevString.length)
    );

    setDomainsArray(
      domainEndings.map(
        ending =>
          domainString.substring(0, start) +
          e.native +
          domainString.substring(end, domainString.length) +
          ending
      )
    );

    inputEl.current.focus();
    // the line below doesn't work!
    // inputEl.current.setSelectionRange(start + e.native.length, end + e.native.length)

    //this one does, but is not good practice..
    setTimeout(
      () =>
        inputEl.current.setSelectionRange(
          start + e.native.length,
          end + e.native.length
        ),
      10
    );
  }}
/>

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744260131a4565591.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信