繁体   English   中英

在 React 中,最初使用 props 的值设置状态,然后使用 FormControl 更新 state

[英]In React, initially setState using value from props, and then update state using FormControl

不确定如何将其变成 stackoverflow 中的可重现示例,但我们有以下 React 组件,它创建一个 SVG 图形,它具有可编辑的 header 文本(可以单击文本进行编辑并键入以编辑文本)利用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 textOurGraph组件中 SVG 中的文本不会更新为false text ,即使 prop 值成功完成更新为false text

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

编辑- 虽然从道具值立即设置状态()似乎是一种反模式,但我们需要 graphText 作为 state 中的变量,因为它在 FormControl 中更新,我们希望道具值headerText成为默认值graphText 最重要的是,每当headerText发生变化时,我们都希望使用在headerText中传递的新属性值覆盖FormControlgraphText中设置的任何值。

这是反模式的典型例子。 React 不会重新初始化 state。为了使其正常工作,您可以执行以下操作:

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>);
 }

此外,更好的方法是将此 state 置于上下文中并从上下文中导出 onChange function 并使用自定义挂钩对其进行操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM