繁体   English   中英

道具被 state 覆盖更改?

[英]props being overwritten by state change?

我在我的代码中遇到了一个奇怪的错误,我正在努力理解原因。

简而言之,我传递给功能组件的道具似乎被 state 更改覆盖(这绝对不会传播到父级)。 我猜这是因为我在创建新对象时做错了,然后这些新对象用于更新 state,但我很难知道在哪里。

我正在使用 react-select,这是触发错误的更改 function 。 我不认为这本身就是问题所在,因为我在项目的其他地方使用过它并且没有遇到这个错误。

这是我的代码的精简版本(已删除导入):

interface IPropertyValue {
    field1: number;
    field2: number;
    field3: number;
    field4: string;        
}

interface INestedPropertyType {
    systemProperty?: IPropertyValue;
}

interface IPropertyType {
    current: INestedPropertyType;
    desired: INestedPropertyType;
}

interface IComponentProps {
    currentProperty: IPropertyType;
}

export function Component(passedProps: IDynamicPropsType) {
    const props = passedProps as IComponentProps;
    const [propName, setPropName] = useState(props.currentProperty);

    const editValue = (typeOfProperty: 'current' | 'desired', newValue: string) => {

        let existingPropName = {...propName} as IPropertyType; // create a new object from existing one
        let alteredPropName = {} as ISystemProperty; // we reassign this later on based on typeOfProperty

        if(typeOfProperty === 'current') {
            if(existingPropName.current.systemProperty) {
                alteredPropname = {...existingPropName.current.systemProperty} as IPropertyValue;
            } else {
                existingPropName.current.systemProperty= {} as IPropertyValue;
                alteredPropName= {} as IPropertyValue;
            }
        } else if (typeOfProperty=== 'desired') {
            if(existingPropName.desired.systemProperty) { // could be undefined...
                // is defined, create a new object for it using existing values
                existingPropName= {...existingPropName.desired.systemProperty} as IPropertyValue;
            } else {
                // not defined, create empty object for it
                existingLineage.desired.systemProperty= {} as IPropertyValue;
                alteredPropName= {} as IPropertyValue;
            }
        }

        const newValues = newValue.split('|'); // this comes from the select option; it's a string separated by '|' symbols. It will always be 4 values long.
        if(newValues.length === 4) {
            alteredPropName = {
                ...alteredPropName,
                field1: parseInt(newValues[0], 10),
                field2: parseInt(newValues[1], 10),
                field3: parseInt(newValues[2], 10),
                field4: newValues[3]
            }
        }

        // update the relevant property with the updated object
        if(typeOfProperty === 'current') {
            existingPropName.current.systemProperty = alteredPropName;
        } else if(typeOfProperty=== 'desired') {
            existingPropName.desired.systemProperty = alteredPropName;
        }

        // update the state
        setPropName(existingLineage);
    }

    // here's the weird part. 'props' is changed after the editValue function is called, even though it should be passed in from the parent component and left unchanged (apart from casting it to IComponentProps)
    console.log(props);

    return (<>
        <Select
            options={<options here>}
            onChange={(selectedOption: ValueType<any>) => {
                editValue('current', selectedOption.value);
            }}
        />
        <Select
            options={<options here>}
            onChange={(selectedOption: ValueType<any>) => {
                editValue('desired', selectedOption.value);
            }}
        />
    </>);
}

代码中有一些奇怪的部分,例如将passedPropsprops ,但它们的存在是有原因的 - 父组件是一个在多个其他组件之间共享的包装器。

是的你是对的。 您的道具被覆盖,因为您直接将它们传递

useState(props.currentProperty)

在 Javascript 中,对象是引用类型。 调用 editValue 将导致更新嵌套对象。

您可以在将道具传递给useState之前创建道具的深层副本。 简单的方法是使用JSON.stringifyJSON.parse

const [propName, setPropName] = useState(JSON.parse(JSON.stringify(props.currentProperty)));

暂无
暂无

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

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