{"record":{"id":"196902b50f2f4018","repo":"HelloZeroNet/ZeroNet","slug":"class-property-may-not-be-updated-use-the-clas","errorCode":null,"errorMessage":"\"class\" property may not be updated. Use the \"classes\" property for conditional css classes.","messagePattern":"\"class\" property may not be updated\\. Use the \"classes\" property for conditional css classes\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"plugins/UiConfig/media/js/all.js","lineNumber":378,"sourceCode":"                }\n            }\n        }\n    };\n    var updateProperties = function (domNode, previousProperties, properties, projectionOptions) {\n        if (!properties) {\n            return;\n        }\n        var propertiesUpdated = false;\n        var propNames = Object.keys(properties);\n        var propCount = propNames.length;\n        for (var i = 0; i < propCount; i++) {\n            var propName = propNames[i];\n            // assuming that properties will be nullified instead of missing is by design\n            var propValue = properties[propName];\n            var previousValue = previousProperties[propName];\n            if (propName === 'class') {\n                if (previousValue !== propValue) {\n                    throw new Error('\"class\" property may not be updated. Use the \"classes\" property for conditional css classes.');\n                }\n            } else if (propName === 'classes') {\n                var classList = domNode.classList;\n                var classNames = Object.keys(propValue);\n                var classNameCount = classNames.length;\n                for (var j = 0; j < classNameCount; j++) {\n                    var className = classNames[j];\n                    var on = !!propValue[className];\n                    var previousOn = !!previousValue[className];\n                    if (on === previousOn) {\n                        continue;\n                    }\n                    propertiesUpdated = true;\n                    if (on) {\n                        classList.add(className);\n                    } else {\n                        classList.remove(className);\n                    }","sourceCodeStart":360,"sourceCodeEnd":396,"githubUrl":"https://github.com/HelloZeroNet/ZeroNet/blob/454c0b2e7e000fda7000cba49027541fbf327b96/plugins/UiConfig/media/js/all.js#L360-L396","documentation":"After initial render, maquette forbids changing the `class` string property on updates; static class changes would require patching in ways maquette does not reconcile. Conditional classes must be expressed with the `classes` object, whose boolean entries maquette adds/removes from the DOM classList on each render.","triggerScenarios":"A subsequent projection.update(updatedVnode) (or projector render pass) supplies a vnode whose `class` property value differs from the previous render's value.","commonSituations":"Building dynamic class strings with template literals or conditionals (class: isActive ? 'a' : 'b'); toggling state classes on re-render; porting code that assumed class behaves like other attributes.","solutions":["Move conditional classes into `classes`: { classes: { 'is-active': isActive } } and keep `class` constant (or omit it).","If the base class never changes, keep it in `class` and only vary `classes`.","Restructure so each distinct class combination is represented by different vnode structure/keys if truly dynamic static classes are needed.","As a last resort, manage the class directly via a custom afterCreate/afterUpdate handler, but this bypasses the VDOM diff."],"exampleFix":"// before\nh('div', { class: isActive ? 'card active' : 'card' })\n// after\nh('div', { class: 'card', classes: { active: isActive } })","handlingStrategy":"validation","validationCode":"function assertClassStable(prevProps, nextProps) {\n  if (prevProps && nextProps && prevProps.class !== nextProps.class) {\n    throw new Error('Move conditional classes into the classes object');\n  }\n}","typeGuard":"function classIsConditionalSafe(prev, next) {\n  return prev == null || next == null || prev.class === next.class;\n}","tryCatchPattern":"try {\n  projection.update(vnode);\n} catch (e) {\n  if (e.message.indexOf('\"class\" property may not be updated') !== -1) {\n    console.error('Use classes: { name: bool } for conditional classes');\n  }\n  throw e;\n}","preventionTips":["Keep the `class` property value a constant string; express all variability via `classes`.","Never build the class attribute from state or template literals inside render.","Code-review list/dynamic components for class-in-render patterns.","If class must truly change, re-create the projection instead of updating it."],"tags":["maquette","class","rerender","virtual-dom"],"backgroundTag":"class-property-not-updatable","analyzedSha":"454c0b2e7e000fda7000cba49027541fbf327b96","analyzedAt":"2026-09-02T19:46:57.278Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}