【问题标题】:React variable not reactive in external event反应变量在外部事件中没有反应
【发布时间】:2021-06-13 21:11:38
【问题描述】:

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

我正在尝试将 CodeMirror 包装在 React 应用程序中,但遇到了一些麻烦。不知道怎么解决。

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

在最后一个处理程序中,我需要访问一个使用useState (isFocused) 设置的reactive 变量。 该变量在该函数的上下文中不是反应性的。它被读取为默认值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 参数。

【问题讨论】:

    标签: reactjs react-hooks reactive-programming codemirror


    【解决方案1】:

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

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

    (查看页面底部的演示链接)

    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

    【讨论】:

    • 上面的例子和我的场景有点不同。在事件处理程序中,您正在设置状态(这将起作用)。在我的示例中,我需要获取状态并且它不是响应式的。
    • 我忘了提一件事,handleChange 方法从 CodeMirror instancechange 获取两个参数。我更新了你的 stackblitz 以包含这样的内容:const handleChange = (isF, instance, change) 现在它可以工作了。 isF 在该函数内部是响应式的,instancechange 参数被传递给该方法。我只是不知道如何:) 我的意思是...这解决了我的问题,但我不知道 React 是如何做到的。感谢您的帮助!我真的很感激。
    • 老实说,我无法解释为什么。也许它与同一组件上的 2 个更改事件侦听器有关:onChange 和 on。 ('改变', ...) ???
    • 我要回到这个话题。它实际上不起作用。检查我的示例here。当来自 codemirror 的回调运行时,isFocused 变量仍然是非反应性的。
    • @adrianthedev 我的解决方案回答了您的问题。您的代码已更改,因此问题也发生了。与其提出问题、接受解决方案、更改代码、拒绝解决方案等。我建议您查看react-codemirrorreact-codemirror2 包,它们的存在可能是有充分理由的。
    猜你喜欢
    • 2018-05-11
    • 1970-01-01
    • 2018-01-20
    • 2022-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-24
    • 1970-01-01
    相关资源
    最近更新 更多