反应变量在外部事件中不反应

React variable not reactive in external event

我是一名 Vue 开发人员,正在尝试开发 React 应用程序。

我正在尝试将 CodeMirror 包装在 React 应用程序中,但我 运行 遇到了一些麻烦。不确定如何修复它。

我正在实例化一个 CodeMirror 编辑器并将一些事件处理程序附加到它。 这些处理程序是这样的: 当您聚焦编辑器时,isFocused 变量变为 true。 当您将焦点移出编辑器时,isFocused 变量变为 false。 当您在编辑器中输入时,如果 isFocused 变量为真,您应该执行一些操作。

在最后一个处理程序中,我需要访问一个 reactive 变量集 useState (isFocused)。 该变量在该函数的上下文中不是反应性的。它被读取为默认值 false.

组件看起来像这样:

import React, {useState, useEffect, useRef} from 'react';
import 'codemirror/lib/codemirror.css'
import 'codemirror/mode/javascript/javascript'
import CodeMirror from 'codemirror'
import './App.css';

function App() {
  const textArea = useRef()
  const [isFocused, setIsFocused] = useState(false)
  const [data, setData] = useState('sample data')
  

  const handleChange = () => {
      console.log('isFocused->', isFocused);

    if (isFocused) {
     // do something here 
    }
  }

  const handleEditorFocus = () => {
    setIsFocused(true)
  }

  const handleEditorBlur = () => {
    setIsFocused(false)
  }

  useEffect(() => {
    const editor = CodeMirror.fromTextArea(textArea.current)
    editor.on('change', handleChange)
    editor.on('focus', handleEditorFocus)
    editor.on('blur', handleEditorBlur)

    return () => {
      editor.toTextArea()
    } 
  }, []);

  return (
    <div>
      {isFocused ? 'focused' : 'not focused'}
      <textarea
        ref={textArea}
        value={data}
        onChange={(e) => setData(e.target.value)}
      ></textarea>
    </div>
    )
};

export default App;

请指出这个问题的正确方向。

谢谢!

更新: 我什至做了一个 repl.it here.

更新 2 stackblitz 上更好的演示。 我基本上需要访问 handleChange 函数中的 instancechange 参数。

添加一个带有回调的 useEffect 函数到 handleChange 并将其作为参数传递 isFocused

PS: 不要忘记 Boolean() 显示 isFocused 的状态,否则它 returns 一个对象。

(参见页面底部的演示 link)

import React, { useState, useEffect, useRef } from 'react';
import 'codemirror/lib/codemirror.css';
import 'codemirror/mode/javascript/javascript';
import CodeMirror from 'codemirror';

export default function App() {
  const textArea = useRef();
  const [isFocused, setIsFocused] = useState(false);
  const [data, setData] = useState('sample data');

  const handleChange = isF => { 
    console.log('isFocused->', Boolean(isF));           // here

    if (isFocused) {
      // ...
    }
  };

  const handleEditorFocus = () => {
    setIsFocused(true);
  };

  const handleEditorBlur = () => {
    setIsFocused(false);
  };

  useEffect(() => {                                     // here
    handleChange(isFocused);
  }, [isFocused]);

  useEffect(() => {
    const editor = CodeMirror.fromTextArea(textArea.current);
    editor.on('change', handleChange);
    editor.on('focus', handleEditorFocus);
    editor.on('blur', handleEditorBlur);

    return () => {
      editor.toTextArea();
    };
  }, []);

  return (
    <div>
      {isFocused ? 'focused' : 'not focused'}
      <textarea
        ref={textArea}
        value={data}
        onChange={e => setData(e.target.value)}
      />
    </div>
  );
}

演示:Stackblitz