skip to Main Content

I’m trying to partially update userData object

// Types named randomly...

export type authDetails = {
    info: {
        token: String,
        somethingElse: String
    },
    moreInfo: {
        something: String
    }
}

...

export type userData = {
    auth: authDetails,
    config: configDetails,
    params: paramsDetails
}

const [userData, setUserData] = useState<userData>();

setUserrData((prev: any) => ({
    ...prev,
    auth : {
        info: {
            token: newToken
        }
    },
    params: {
        someParam: newParam
    }
}));

Is it even possible? I can’t find any way to do that. I wanna change some data and keep other values unchanged. ...prev didn’t work.

(new to typescript and react)

2

Answers


  1. This is what you want to do:

    setUserrData((prev: any) => ({
        ...prev,
        auth : {
            ...prev.auth,
            info: {
                token: newToken
            }
        },
        params: {
            ...prev.params,
            someParam: newParam
        }
    }));
    

    You need to still spread the values of the updated properties.

    Login or Signup to reply.
  2. Couple things I’d like to mention since you’re new to TS and React.

    Usually, types should be defined in PascalCase and the string type is a native keyword and is defined in lowercase, so your types would look like:

    export type AuthDetails = {
        info: {
            token: string;
            somethingElse: string;
        };
        moreInfo: {
            something: string;
        };
    }
    
    export type UserData = {
        auth: AuthDetails;
        config: ConfigDetails;
        params: ParamsDetails;
    }
    

    And about the issue that you’re facing, when you’re dealing with updating nested fields, one way to solve the issue is using spread and you must use it to fill all the nested object like the following:

    const [userData, setUserData] = useState<UserData>();
    
    setUserData((currentUserData) => ({
        ...currentUserData,
        auth: {
            ...currentUserData.auth,
            info: {
                ...currentUserData.auth.info,
                token: newToken,
            },
        },
        params: {
            ...currentUserData.params,
            someParam: newParam,
        }
    }));
    

    Another way is cloning that value and replace directly the fields and return the name value:

    const [userData, setUserData] = useState<UserData>();
    
    setUserData((currentUserData) => {
        const clonedCurrentUserData = { ...currentUserData };
    
        clonedCurrentUserData.auth.info.token = newToken;
        clonedCurrentUserData.params.someParam = newParam;
    
        return clonedCurrentUserData;
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search