我正在使用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>
答案 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>
)
}