在React中,最初setState使用props中的value,然后使用FormControl更新状态



不确定如何在stackoverflow内将其变为可重复的示例,但我们有以下React组件,该组件创建SVG图形,具有可编辑的标题文本(可以单击文本进行编辑并键入编辑文本)利用foreignObjectFormControl

import { FormControl } from 'react-bootstrap';
function OurGraph({ headerText }) {
const [graphText, setGraphText] = useState(headerText);
// create editable header
const ourHeader =
(<foreignObject width='100%' height='40'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<FormControl
className='modal-input no-style'
type='text'
value={graphText}
onChange={e => setGraphText(e.target.value)}
name='subheader'
placeholder=''
/>
</div>
</foreignObject>);
// and return
return (<svg>{ourHeader}</svg>);
}

,我们有这个父组件为OurGraph组件更新默认的headerText:

function Parent() {
const [button, setButton] = useState(true);
const buttonElement =
(<button onClick={() => setButton(!button)}>
CLICK ME
</button>);
return (
{buttonElement}
<OurGraph headerText={button === true ? 'true text' : 'false text'} />
)
}

这是如此接近工作的预期…当组件最初呈现时,true text显示为SVG中的文本,很好!当我们点击文本时,文本是可编辑的,很好!

问题是,当我们点击CLICK ME按钮时,它将OurGraph中的headerText道具从true text更改为false text,OurGraph组件中的SVG中的文本不即使prop值成功更新到false text,也要更新到false text

为什么会这样?我们如何解决这个问题,使变化的道具值反映在SVG的表单控件的文本?我们认为新的headerText值会导致const [graphText, setGraphText] = useState(headerText);graphText设置一个新的值,但是当headerText道具从true text变为false text时,graphText并没有改变。

编辑-虽然它看起来像一个反模式立即setState()从一个道具值,但我们需要graphText作为一个变量的状态,因为它是在FormControl中更新的,我们希望道具值headerTextgraphText的默认值。最重要的是,无论何时headerText发生变化,我们都希望用headerText传递的新prop值覆盖graphTextFormControl设置的任何值。

这是一个典型的反模式示例。React不会重新初始化状态。为了使它工作,你可以这样做:

import { FormControl } from 'react-bootstrap';
import {useEffect} from 'react';
function OurGraph({ headerText }) {
const [graphText, setGraphText] = useState(headerText);
useEffect(()=>{
setGraphText(headerText)
},[headerText])
// create editable header
const ourHeader =
(<foreignObject width='100%' height='40'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<FormControl
className='modal-input no-style'
type='text'
value={graphText}
onChange={e => setGraphText(e.target.value)}
name='subheader'
placeholder=''
/>
</div>
</foreignObject>);
// and return
return (<svg>{ourHeader}</svg>);
}

此外,更好的方法是将此状态引入上下文并从上下文导出onChange函数,并使用自定义钩子对其进行操作。

相关内容

最新更新