React contentEditable和光标位置

时间:2017-07-25 14:30:19

标签: javascript reactjs

我有简单的组件

export class MyComponent implements OnInit {
   isLoaded = false;
   stronglyTypedData1: StrongData1[];
   stronglyTypedData2: StrongData2[];

   constructor(private myService:MyService){ }

   ngOnInit(){
      var requests [ 
         this.myService.getStronglyTypedData1(),
         this.myService.getStronglyTypedData2()
      ];
      Observable.forkJoin(requests).subscribe(
         results => {
            this.stronglyTypedData1 = results[0];
            this.stronglyTypedData2 = results[1];
            this.isLoaded = true;
         });
   }
}

组件有效,但我的光标始终位于第一个位置,而不是渲染文本。

我在此论坛中测试了一些示例,但它对我不起作用。

我使用React 15.6.1并在chrome(Os X)上测试它。我有什么提示可以解决这个问题吗?

2 个答案:

答案 0 :(得分:0)

使用useRef的解决方案如下所示。

keep the data within custom input with useRef

此处useRef会将默认值/初始值与组件渲染周期分开,因此它将保留原始值,而不受我们在react组件中执行的其他类型操作的影响。

此组件有两件事

  1. 这将使用onChange方法将用户输入发送到父组件
  2. 从名为prop的父组件中获取默认值,并将其呈现在自定义输入框中(使用value创建的自定义输入框中)

我添加了一个代码沙箱,链接here,使用它来查看其工作原理!

代码沙箱示例包含两个组件

  • 一个是contentEditable,它解决了ContentEditableWithRef的问题,useRef是一个不受控制的组件,并且
  • 另一个组件是ContentEditable,它使用useState解决同一问题。

答案 1 :(得分:-1)

import React, { useRef } from 'react';

const ContentEditable = ({ value, onChange = () => {}, ...props }) => {
    const state = useRef({ value, prevValue: null, key: null });

    if (state.current.prevValue !== value) {
        state.current.value = value;
        state.current.key = Date.now();
    }

    const _handleInput = (event) => {
        const value = event.target.innerText;
        state.current.prevValue = value;
        onChange(value);
    };

    return (
        <div
            {...props}
            key={state.current.key}
            role="textbox"
            contentEditable={true}
            dangerouslySetInnerHTML={{ __html: state.current.value }}
            onInput={_handleInput}
        />
    );
};
export default ContentEditable;

用法:

const [value, setValue] = useState("initial test");

<ContentEditable
  value={value}
  onChange={setValue}
/>