无法使用React JS编辑输入文本

时间:2019-11-14 14:53:28

标签: javascript html reactjs events

我正在使用React JS,我有一个文本字段,当用户单击不同的UI组件时,该文本字段应更改其内容。我还希望能够在该文本字段中编辑文本(稍后,我想将该文本发送到UI组件,但这是另一回事了)。到目前为止,我已经收到了这段代码

import React, { useContext } from 'react'
import './ContextualMenu.css'
import { EditorContext } from '../../EditorBase'

const ContextualMenu = props => {
  const editorContext = useContext(EditorContext)
  const handleUpdates = (event) => {
    console.log(event.target.value)
  }
  const displayNodeAttr = () => {
    return (
      <>
        <div className="menu-title">{editorContext.selectedNode.nodeType}</div>
        <div>
          <div className="menu-item">
            <div className="menu-item-label">Name</div>
            <div className="menu-item-value">
              <input
                className="menu-item-input"
                type="text"
                value={editorContext.selectedNode.nodeAttr.name}
                onChange={handleUpdates}
              />
            </div>
          </div>
        </div>
      </>
    )
  }

  return (
    <div id="c-contextual-menu">
      {editorContext.selectedNode.nodeAttr && displayNodeAttr()}
    </div>
  )
}

export default ContextualMenu

这使文本始终返回到用户单击组件时设置的原始文本。如果我将第21行(value={editorContext.selectedNode.nodeAttr.name})替换为placeholder={editorContext.selectedNode.nodeAttr.name},则当用户单击UI组件时,提示总是显示正确的文本,但它将显示为提示,我希望将其显示为文本。 在我看来,输入文本字段检测到一个更改(在更改事件上有一个侦听器或类似的东西),它立即将文本还原为原始文本,从而使其基本上不可编辑。有什么想法吗?

更新: 在@alireza和@Juviro回答之后,我更改了代码,原因是最初选择的节点为空,而当用户选择该节点时,该节点将不为空。所以代码现在看起来像这样(只是相关部分):

const ContextualMenu = props => {
  const editorContext = useContext(EditorContext)
  const val = editorContext.selectedNode && editorContext.selectedNode.nodeAttr ? editorContext.selectedNode.nodeAttr.name : ''
  const [value, setValue] = useState(val)
  const handleUpdates = (event) => {
    setValue(event.target.value)
    console.log(event.target.value)
  }
  const displayNodeAttr = () => {
    return (
      <>
        <div className="menu-title">{editorContext.selectedNode.nodeType}</div>
        <div>
          <div className="menu-item">
            <div className="menu-item-label">Name</div>
            <div className="menu-item-value">
              <input
                className="menu-item-input"
                type="text"
                value={value}
                onChange={handleUpdates}
              />
            </div>
          </div>
        </div>
      </>
    )
  }

  return (
    <div id="c-contextual-menu">
      {editorContext.selectedNode.nodeAttr && displayNodeAttr()}
    </div>
  )
}

现在的问题是,当用户单击UI组件(节点)时,输入字段永远不会设置为任何值。好像该值是在页面加载时设置的,然后在用户选择组件(节点)时从未更新过。如果现在我使用val而不是value像这样:value={val},则输入字段将正确更新,但是我又回到了无法编辑其内容的旧问题。 / p>

3 个答案:

答案 0 :(得分:1)

此组件始终显示与editorContext.selectedNode.nodeAttr.name相同的值 您应该在组件中使用状态来处理其值。

import React, { useContext, useState } from 'react'
import './ContextualMenu.css'
import { EditorContext } from '../../EditorBase'

const ContextualMenu = props => {
  const editorContext = useContext(EditorContext)
  const [value, setValue] = useState(editorContext.selectedNode.nodeAttr.name)
  const handleUpdates = (event) => {
    setValue(event.target.value)
    console.log(event.target.value)
  }
  const displayNodeAttr = () => {
    return (
      <>
        <div className="menu-title">{editorContext.selectedNode.nodeType}</div>
        <div>
          <div className="menu-item">
            <div className="menu-item-label">Name</div>
            <div className="menu-item-value">
              <input
                className="menu-item-input"
                type="text"
                value={value}
                onChange={handleUpdates}
              />
            </div>
          </div>
        </div>
      </>
    )
  }

  return (
    <div id="c-contextual-menu">
      {editorContext.selectedNode.nodeAttr && displayNodeAttr()}
    </div>
  )
}

我还没有测试,但是应该可以。

更新 要根据props的值更新值,您应该使用useEffect

import React, { useContext, useEffect, useState } from 'react'
import './ContextualMenu.css'
import { EditorContext } from '../../EditorBase'

const ContextualMenu = props => {
  const editorContext = useContext(EditorContext)
  const val = editorContext.selectedNode && editorContext.selectedNode.nodeAttr.name ? editorContext.selectedNode.nodeAttr.name : ''
  const [value, setValue] = useState(val)

  const handleUpdates = (event) => {
    setValue(event.target.value)
    console.log(event.target.value)
  }

  useEffect(()=>{
    if( val !== value) // Prevent redundant updates
      setValue(val)
  })

  const displayNodeAttr = () => {
    return (
      <>
        <div className="menu-title">{editorContext.selectedNode.nodeType}</div>
        <div>
          <div className="menu-item">
            <div className="menu-item-label">Name</div>
            <div className="menu-item-value">
              <input
                className="menu-item-input"
                type="text"
                value={value}
                onChange={handleUpdates}
              />
            </div>
          </div>
        </div>
      </>
    )
  }

  return (
    <div id="c-contextual-menu">
      {editorContext.selectedNode.nodeAttr && displayNodeAttr()}
    </div>
  )

答案 1 :(得分:1)

@alireza的解决方案看起来不错,只需替换

useState(event.target.value)

使用

setValue(event.target.value)

答案 2 :(得分:1)

setValue的值更改时,您可以使用effect hook来调用val函数


import React, { useEffect, useState, useContext } from 'react'

const ContextualMenu = props => {
  const editorContext = useContext(EditorContext)
  const val = editorContext.selectedNode && editorContext.selectedNode.nodeAttr ? editorContext.selectedNode.nodeAttr.name : ''
  const [value, setValue] = useState(val)

  useEffect(() => {
    setValue(val)
  }, [val])

  const handleUpdates = (event) => {
    setValue(event.target.value)
    console.log(event.target.value)
  }
  const displayNodeAttr = () => {
    return (
      <>
        <div className="menu-title">{editorContext.selectedNode.nodeType}</div>
        <div>
          <div className="menu-item">
            <div className="menu-item-label">Name</div>
            <div className="menu-item-value">
              <input
                className="menu-item-input"
                type="text"
                value={value}
                onChange={handleUpdates}
              />
            </div>
          </div>
        </div>
      </>
    )
  }

  return (
    <div id="c-contextual-menu">
      {editorContext.selectedNode.nodeAttr && displayNodeAttr()}
    </div>
  )
}