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

hgb9j2n6  于 2023-01-24  发布在  Java
关注(0)|答案(1)|浏览(129)

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

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文本不会更新为false text,即使属性值成功更新为false text
为什么会这样?我们如何解决这个问题,使属性值的变化反映在SVG的Form控件中?我们认为新的headerText值会导致const [graphText, setGraphText] = useState(headerText);graphText设置新值,但是当headerText属性从true text更改为false text时,graphText没有发生变化。

Edit-尽管立即setState看起来像是反模式(),但是我们需要graphText作为state中的变量,因为它在FormControl中更新,并且我们希望prop值headerTextgraphText的默认值。我们想要用在headerText中传递的新的prop值来覆盖从FormControl设置的graphText中的任何值。

wj8zmpe1

wj8zmpe11#

这是一个典型的反模式例子。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函数,并使用自定义钩子来操作它。

相关问题