【问题标题】:react input cursor moves to the end after update更新后反应输入光标移动到末尾
【发布时间】:2017-07-19 19:42:49
【问题描述】:

当我更新输入字段中的值时,光标会移动到字段的末尾,但我希望它保持在原来的位置。什么可能导致此问题?

<Input
  type="text"
  placeholder="test
  name="test"
  onChange={getOnChange(index)}
  value={testVal}/>

其中 Input 是文本输入字段的组件,getOnChange 是:

const getOnChange = (index) =>
  (event) => props.onChangeTest(event, index);

然后将其转移到父组件,在那里我通过 Redux 调度更新状态。我可以看到状态正在正常更新,但问题是光标没有停留在原位,并且总是移动到文本的末尾

【问题讨论】:

标签: reactjs redux


【解决方案1】:

如果光标跳到字段的末尾,通常意味着您的组件正在重新安装。这可能是由于每次更新父项中某处的值或组件树中的更改时关键属性发生更改。不看更多代码很难说。防止重新安装,光标应该停止跳跃。

使用此效果跟踪安装/卸载

useEffect(() => {
   console.log('mounted');

   return () => { 
       console.log('unmounted')
   }
}, []);

【讨论】:

    【解决方案2】:

    这是受控组件设计模式的缺点。我已经面对这个问题很长时间了,只是忍受它。但是有一个想法,我想在业余时间尝试但最终从未尝试过(还)。也许继续我的想法可以帮助您提出您需要的解决方案?

    <Input
      type="text"
      placeholder="test
      name="test"
      onChange={getOnChange(index)}
      value={testVal}
    />
    


    // From props.onChangeTest
    const onChangeTest = (event, index) => {
      // TODO: Memorize the position of the cursor
      this.setState({ testVal: event.target.value })
    
      // Because setState is asynchronous
      setTimeout(() => {
        // TODO:
        // Programmatically move cursor back to the saved position
        // BUT it must increase/decrease based on number of characters added/removed
        // At the same time considering if the characters were removed before or after the position
    
        // Theoretically do-able, but it's very mind-blowing
        // to come up with a solution that can actually 'nail it'
      }, 0)
    }
    


    ★ 如果这花费了太多时间,而您只想完成工作并发布您的应用程序,您可能需要考虑改用不受控制的组件设计模式。

    【讨论】:

      【解决方案3】:

      我建议使用钩子来解决这个问题

      const Component = ({ onChange }) => {
        const [text, setText] = useState("");
        const isInitialRun = useRef(false);
      
        useEffect(() => {
           if (isInitialRun.current) {
              onChange(text);
           } else {
              isInitialRun.current = true;
           }
        }, [text]);
      
        // or if you want to have a delay
      
        useEffect(() => {
           if (isInitialRun.current) {
               const timeoutId = setTimeout(() => onChange(text), 500);
               return () => clearTimeout(timeoutId);
          } else {
               isInitialRun.current = true;
          }
        }, [text])
      
        return (
          <Input
              type="text"
              placeholder="test
              name="test"
              onChange={setText}
              value={text}/>
       );
      }
      
      

      为了防止初始调用,当没有任何变化时使用isInitialRun

      【讨论】:

        【解决方案4】:

        我遇到了同样的问题,这是由于 2 个连续的 setState 语句。更改为单个 setState 解决了该问题。可能对某人有帮助。

        修复前的代码:

        const onChange = (val) => {
         // Some processing here
         this.setState({firstName: val}, () => {
          this.updateParentNode(val)
         })
        }
        
        const updateParentNode = (val) => {
          this.setState({selectedPerson: {firstName: val}})
        }
        

        修复后的代码

        const onChange = (val) => {
        // Some processing here
          this.updateParentNode(val)
        }
        
        const updateParentNode = (val) => {
          this.setState({selectedPerson: {firstName: val}, firstName: val})
        }
        

        【讨论】:

          【解决方案5】:

          你有两个选择。

          1. 使其成为不受控制的输入(以后不能更改输入值)

          2. 使其成为适当控制的输入

          这里缺少代码,所以我不能说问题是什么。 setState 不是问题:https://reactjs.org/docs/forms.html#controlled-components

          如果你在回调中使用setState,React 应该保留光标位置。

          你能举一个更完整的例子吗? testVal 是从组件外部操作的属性吗?

          【讨论】:

            【解决方案6】:

            当您通过代码动态更新输入值时,输入上的光标将被推到最后,这看起来就像您正在做的那样,因为我可以看到value={testVal} :)

            这是使用输入掩码的字段的常见问题!

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-11-08
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-12-17
              • 2021-11-21
              • 1970-01-01
              相关资源
              最近更新 更多