2

I have the following object in my React app:

const processDetails = () => {
    const INIT_ERROR = {
      condition: {
        name:        "",
        description: ""
      },
      treatment: {
        name:         "",
        description:  ""
      },
    }
    
    const [error, setError] = useState(INIT_ERROR);
}

This is connected to a form which takes various values; on submission, it needs to be validated and the value of 'error' is updated where information is missing.

In the validation function, I have, eg:

if(conditionName === "")) {
      setError(...);
}

and I want this to set the value of error.condition.name to "Error - please enter a name for this condition".

How do I do this? I've tried:

setError({ ...error, condition: {...error.condition, name: "Please enter a name for this condition"} });

which seems to work, but then doing the same thing to update error.condition.description, like this:

setError({ ...error, condition: {...error.condition, description: "Please enter a description for this condition"} });

overwrites the value of error.condition.name.

5
  • 1
    "which seems to work, but then doing the same thing to update error.condition.description overwrites the value of error.condition.name." Show us that code. It's really hard to help you understand why code isn't working if you don't show us the code that doesn't work. :-) Commented Mar 29, 2021 at 16:17
  • (Side note: It's not really important, but ... isn't an operator. Operators can't do what ... does. It's just syntax.) Commented Mar 29, 2021 at 16:18
  • It's the same code, but with description instead of name: Commented Mar 29, 2021 at 16:24
  • setError({ ...error, condition: {...error.condition, description: "Please enter a description for this condition"} }); Commented Mar 29, 2021 at 16:24
  • 1
    Hi Sharon - I've folded that comment into the question. Please hit "rollback" on the edit if I got it wrong. Commented Mar 29, 2021 at 17:28

1 Answer 1

3

I've tried:

setError({ ...error, condition: {...error.condition, name: "Please enter a name for this condition"} });

which seems to work, but then doing the same thing to update error.condition.description overwrites the value of error.condition.name.

That's how you do it, but it sounds like you're making two separate calls to setError using that same pattern. That won't work, because as you've found the second one will just overwrite the effect of the first. (Because error isn't updated right away, so when you do ...error.condition, you're still using the old condition.name.) Do a single call with both updates:

setError({
    ...error,
    condition: {
        ...error.condition,
        name: "Please enter a name for this condition",
        description: "Updated description here"
    }
});

In a comment you've said:

Sometimes I only want to update one of them though... basically if conditionName is empty, then I want to update error.condition.name; if conditionDesc is empty then I want to update error.condition.description. Is there a way to do one after the other?

Yes, there are a couple of ways. Probably the easiest is: Since you know that you're going to update error and condition, make a shallow copy of both, then set either name or description or both, then do the setError:

// Make a shallow copy of both `error` and `error.condition`
const updatedError = {...error, condition: {...error.condition}};
// Now it's okay to directly assign to them
if (conditionName === "") {
    updatedError.condition.name = "Please enter a name for this condition";
}
if (conditionDoc === "") {
    updatedError.condition.description = "Updated description";
}
// Now we've made all our updates, we set state
setError(updatedError);

You could combine all of that into one all-singing, all-dancing call to setError, but it becomes hard to read, hard to debug, and hard to maintain:

// I don't recommend this
setError({
    ...error,
    condition: {
        ...error.condition,
        name: conditionName === ""
            ? "Please enter a name for this condition"
            : error.condition.name,
        description: conditionDoc === ""
            ? "Updated description"
            : error.condition.description,
    },
});
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks. Sometimes I only want to update one of them though... basically if conditionName is empty, then I want to update error.condition.name; if conditionDesc is empty then I want to update error.condition.description. Is there a way to do one after the other?
@Sharon - Yup -- I've added to the end of the answer.
Thank you. I made a shallow copy and that's working.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.