It's a short post that describes how to easily update Managed Metadata Field value using SharePoint REST API or PnPJS.


Although the Title of the post is about REST API and PnPJS I'll describe the process using PnPJS only as it is easier and absolutely identical to REST API.
Usually, to update list item we use update for the list item like that:

pnp.sp.web.lists.getByTitle('List').items.getById(1).update({
  Title: 'New Title',
  CustomField: 'Field Value'
});
The documentation for the update method can be found here
But this method is not very convenient when we want to update Managed Metadata Field value. And especially if the field can contain multiple terms selected.
Even for a single term the call will look like that:
pnp.sp.web.lists.getByTitle('List').items.getById(1).update({
  MetaData: {
    __metadata: { "type": "SP.Taxonomy.TaxonomyFieldValue" },
    Label: "1",
    TermGuid: "6eccf028-399c-486d-9260-72c81f2d5344",
    WssId: -1
  }
});
where Label is not a term label but its ID. If you don't have terms localization it will be "1". But anyway, it's not really cool to construct such objects, right?
That's why I would recommend to use another available method: validateUpdateListItem.
In this method we need to provide array of objects with the next properties:
{
  ErrorMessage: null,
  FieldName: your_field_name,
  FieldValue: field_value,
  HasException: false
}
And for the Managed Metadata Field the FieldValue value can be constructed really easily: term_label + "|" + term_id + ";"
And this format works both for single value and multiple values
So, for example we have Categories field and we want to set the value to contain terms "HR" and "Benefits". We can do that like this:
pnp.sp.web.lists.getByTitle('List').items.getById(1).validateUpdateListItem([{
  ErrorMessage: null,
  FieldName: "Categories",
  FieldValue: "HR|6192598e-8273-4527-89f1-2cd9becb078e;Benefits|6c2d4c17-080a-4a41-b022-766f068fcf73",
  HasException: false
}]);
If you want to update multiple fields, just add them to the array:
pnp.sp.web.lists.getByTitle('List').items.getById(1).validateUpdateListItem([{
  ErrorMessage: null,
  FieldName: "Categories",
  FieldValue: "HR|6192598e-8273-4527-89f1-2cd9becb078e;Benefits|6c2d4c17-080a-4a41-b022-766f068fcf73",
  HasException: false
}, {
  ErrorMessage: null,
  FieldName: "Title",
  FieldValue: "New Title",
  HasException: false
}]);
As a cocnlusion, for simple field types update method is easier, but for such fields as Managed Metadata validateUpdateListItem is better.

That's it!
Have fun!