簡體   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