jjzjj

javascript - React Meteor, react Prop 和内部状态

coder 2023-11-04 原文

我有一个组件

import React, { Component } from 'react'
import { EditorState, convertToRaw } from 'draft-js'
import { Editor } from 'react-draft-wysiwyg'
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css'
import draftToHtml from 'draftjs-to-html'

import toolbarOptions from './JpuriTextEditorOptions'

export default class TextEditor extends Component {
  state = {
    editorState: this.props.editorState
  }

  componentWillReceiveProps = nextProps => {
    console.warn('componentWillReceiveProps')
    console.log('nextProps.editorState', nextProps.editorState)
    console.log('this.props.editorState', this.props.editorState)

    this.setState({editorState: nextProps.editorState})
  }

  onEditorStateChange = editorState => this.setState({editorState})

  onBlur = () => this.props.onBlur({key: this.props.myKey, value: draftToHtml(convertToRaw(this.state.editorState.getCurrentContent()))})

  render () {
    return (
      <Editor
        wrapperClassName={this.props.wrapperClassName}
        editorClassName={this.props.editorClassName}
        toolbarClassName={`toolbarAbsoluteTop ${this.props.toolbarClassName}`}

        wrapperStyle={this.props.wrapperStyle}
        editorStyle={this.props.editorStyle}
        toolbarStyle={this.props.toolbarStyle}

        editorState={this.state.editorState}
        onEditorStateChange={this.onEditorStateChange}
        onChange={this.props.onChange}

        toolbarOnFocus
        toolbar={toolbarOptions}

        onFocus={this.props.onFocus}
        onBlur={this.onBlur}
        onTab={this.props.onTab}
      />
    )
  }
}

我传递给它一个响应式 Prop ,this.props.editorState 然后我将它设置在内部状态中以处理那里的变化。只有 onBlur 我将更改保存到 mongo 数据库。

现在有一个问题。 每当我单击编辑器时,我都会多次看到 componentWillReceiveProps 日志。它发生在每次更改时,因此我无法正确使用我的编辑器组件。因为它的光标会随着每次点击和更改而重置为第一个字母。

我正在使用这个 draftjs 库 https://github.com/jpuri/react-draft-wysiwyg

编辑

问题的更多细节。 在构造函数或 componentDidMount 中将状态设置为 this.props.editorState 正在解决初始状态的问题。 但是只剩下一个问题了。 在另一个组件中,我具有直接与数据库一起使用的撤消重做功能。现在,如果我输入一些文本。模糊它,我的更改已保存到数据库中,由于内部文本,我可以看到文本。但是,如果我单击撤消按钮,文本将从数据库中撤消,但是由于内部状态,它在编辑器中仍然可见。所以我必须刷新才能看到我的操作被撤消。 使用 componentWillReceiveProps 可以解决此问题,但是由于某种原因,即使 props 没有更改,每次状态更改时都会调用 componentWillReceiveProps。从而带来上述问题。

最佳答案

如果您正在使用此组件的受控模式,那么您应该在内部设置状态,而不是通过 Prop 从外部设置它。
例如,如果您在收到的每个新 Prop 上设置状态,则没有理由使用内部状态。
根据他们的DOCS看起来你正在遵循他们的受控 EditorState 示例,除了你在每个新 Prop 上覆盖你的状态。
我认为如果您只是从 componentWillReceiveProps 中删除此行为 即设置状态:this.setState({editorState: nextProps.editorState})
它应该像预期的那样工作。

顺便说一句,这是他们的例子:

import React, { Component } from 'react';
import { EditorState } from 'draft-js';
import { Editor } from 'react-draft-wysiwyg';


class ControlledEditor extends Component {
  constructor(props) {
    super(props);
    this.state = {
      editorState: EditorState.createEmpty(),
    };
  }

  onEditorStateChange: Function = (editorState) => {
    this.setState({
      editorState,
    });
  };

  render() {
    const { editorState } = this.state;
    return (
      <Editor
        editorState={editorState}
        wrapperClassName="demo-wrapper"
        editorClassName="demo-editor"
        onEditorStateChange={this.onEditorStateChange}
      />
    )
  }
}

编辑
根据您的评论,状态初始化通常在 constructor 中进行。
但是当你想异步初始化状态时,你不能也不应该在构造函数中(也不在 componentWillMount 中)因为到时候异步操作将完成 render方法将已经被调用。
最好的地方是 componentDidMount 或 eventHandlers,所以在你的情况下 onBlur eventHandler:
import React, { Component } from 'react'; 从 'draft-js' 导入 { EditorState }; import { Editor } from 'react-draft-wysiwyg';

class ControlledEditor extends Component {
  constructor(props) {
    super(props);
    this.state = {
      editorState: EditorState.createEmpty(),
    };
  }

  onEditorStateChange = (editorState) => {
    this.setState({
      editorState,
    });
  };

  onBlur = (event) => {
    // do async stuff here and update state
  };

  render() {
    const { editorState } = this.state;
    return (
      <Editor
        editorState={editorState}
        wrapperClassName="demo-wrapper"
        editorClassName="demo-editor"
        onEditorStateChange={this.onEditorStateChange}
        onBlur={this.onBlur}
      />
    )
  }
}

关于javascript - React Meteor, react Prop 和内部状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46056907/

有关javascript - React Meteor, react Prop 和内部状态的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby-on-rails - 跳过状态机方法的所有验证 - 2

    当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested

  3. ruby - 字符串文字中的转义状态作为 `String#tr` 的参数 - 2

    对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一

  4. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  5. ruby-on-rails - 为模型创建状态属性 - 2

    我想为我的Task模型创建一个status属性,该属性将按以下顺序指示它在三部分进度中的位置:打开=>进行中=>完成。它的工作方式类似于亚马逊包裹的交付方式:已订购=>已发货=>已交付。我想知道设置此属性的最佳方法是什么。我可能是错的,但创建三个独立的bool属性似乎有点多余。实现此目标的最佳方法是什么? 最佳答案 Rails4有一个内置的enummacro.它使用单个整数列并映射到键列表。classOrderenumstatus:[:ordered,:shipped,:delivered]end状态映射如下:{ordered:0,

  6. ruby - 是否可以在不实际发送或读取数据的情况下查明 ruby​​ 套接字是否处于 ESTABLISHED 或 CLOSE_WAIT 状态? - 2

    s=Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)s.connect(Socket.pack_sockaddr_in('port','hostname'))ssl=OpenSSL::SSL::SSLSocket.new(s,sslcert)ssl.connect从这里开始,如果ssl连接和底层套接字仍然是ESTABLISHED,或者它是否在默认值7200之后进入CLOSE_WAIT,我想检查一个线程几秒钟甚至更糟的是在实际上不需要.write()或.read()的情况下关闭。是用select()、IO.select()还是其他方法完成

  7. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  8. ruby - 在 ruby​​ 中生成一个进程,捕获 stdout,stderr,获取退出状态 - 2

    我想从ruby​​rake脚本运行一个可执行文件,比如foo.exe我希望将foo.exe的STDOUT和STDERR输出直接写入我正在运行rake任务的控制台.当进程完成时,我想将退出代码捕获到一个变量中。我如何实现这一目标?我一直在玩backticks、process.spawn、system但我无法获得我想要的所有行为,只有部分更新:我在Windows上,在标准命令提示符下,而不是cygwin 最佳答案 system获取您想要的STDOUT行为。它还返回true作为零退出代码,这可能很有用。$?填充了有关最后一次system调

  9. ruby - 是否可以从也在该模块中的类内部调用模块函数 - 2

    在这段Ruby代码中:ModuleMClassC当我尝试运行时出现“'M:Module'的未定义方法'helper'”错误c=M::C.new("world")c.work但直接从另一个类调用M::helper("world")工作正常。类不能调用在定义它们的同一模块中定义的模块函数吗?除了将类移出模块外,还有其他解决方法吗? 最佳答案 为了调用M::helper,你需要将它定义为defself.helper;结束为了进行比较,请查看以下修改后的代码段中的helper和helper2moduleMclassC

  10. ruby - 无法安装 gem - make 未被识别为内部或外部命令可运行程序或批处理文件 - 2

    我想在Windows7上安装带有ruby​​1.9.3的rspec-railsgem。我收到一些错误消息,提示无法安装某些json库。所以,我使用下面的说明来解决它。来源=The'json'nativegemrequiresinstalledbuildtools从[rubyinstaller.org][3]下载[Ruby1.9.3][2]从[rubyinstaller.org][3]下载DevKit文件对于Ruby1.9.3,使用[DevKit-tdm-32-4.5.2-20110712-1620-sfx.exe][4]将DevKit解压到路径C:\Ruby193\DevKit运行cd

随机推荐