未捕获的类型错误:无法分配给对象“#<Object>”的只读属性“”
我不知道此代码有何不同。 类 a 是组件,示例是 example.js
import React, {Component} from 'react';
const styles = {
border: {
display: 'inline-block',
height: '19px',
padding: '1px 8px 0',
border: '2px solid',
borderRadius: '12px',
lineHeight: '20px',
fontSize: '14px',
verticalAlign: 'top',
},
default: {
display: 'inline-block',
height: '20px',
padding: '1px 10px 0',
borderRadius: '10px',
lineHeight: '21px',
fontSize: '13px',
verticalAlign: 'top',
},
state: {
display: 'inline-block',
width: '14px',
height: '13px',
paddingTop: '1px',
lineHeight: '14px',
fontSize: '11px',
color: '#fff',
letterSpacing: '-0.5px',
textAlign: 'center',
verticalAlign: 'top',
}
};
class A extends Component {
static defaultProps = {
type: 'default',
};
render() {
const {
label,
style,
type,
...other
} = this.props;
switch (type) {
case 'border':
elementStyle = styles.border;
break;
case 'default':
elementStyle = styles.default;
break;
case 'state':
elementStyle = styles.state;
break;
}
return (
<span style={Object.assign(elementStyle, style)} {...other}>{label}</span>
);
}
}
export default A;
示例代码是 example.js
import A from './A';
export default class Example extends React.Component {
render() {
return (
<div>
<A style={{background: '#fe6969', color: '#fff'}} />
<A style={{background: '#ff8137', color: '#fff'}} />
<A style={{background: '#fcb400', color: '#fff'}} />
</div>
);
}
}
此代码错误为 Uncaught TypeError:无法分配给对象 '#' 的只读属性 'background'
我使用 babel-loader 8、babel7、webpack4
如果我正确执行,Object.assgin({}, elementStyle, style) 可以正常工作。 我认为此错误发生在重新渲染 A 组件时。 我不知道为什么会出现此错误...
请帮帮我。
您需要做的就是使用扩展连接/合并两个对象
{{...elementStyle, ...style}} or
{Object.assign({}, elementStyle , style) }
您应该了解 Object.assign 的工作方式。它将目标对象作为其操作的返回值返回。
因此,在第一个语法中:
Object.assign({}, elementStyle , style)
您正在创建一个 具有 elementStyle 和 style 可枚举属性的全新对象 。
如果您这样做:
Object.assign(elementStyle, style)
那么 elementStyle 本身就是目标对象,因此它将发生变异,并且它将是从 Object.assign 返回的内容。
下面是一个例子,说明了我的意思。
示例 1:
// With no new target object
const original = [{id:1}, {id:2}, {id:3}];
const newArray = original.map(elem => {
return Object.assign(elem, {id:2});
});
console.log('Original object has changed');
console.log(original);
//------------------------------
// With a new target object
const original2 = [{id:1}, {id:2}, {id:3}];
const newArray2 = original2.map(elem => {
return Object.assign({}, elem, {id:2});
});
console.log('Original object has not changed');
console.log(original2);
示例 2:
var styles = {
circle: {backgroundColor: 'yellow', height: '1005', width: '100%'},
circleA: {backgroundColor: 'blue'},
};
因此我们需要所有圆圈都具有默认圆圈样式,但是我们需要更改一些属性,
// background yellow
<div style={styles.circle}></div>
// background blue
<div style={Object.assign(styles.circle, styles.circleA)}></div>
// expeted background yellow, but it's blue. cus styles.circle still have it's merged value
<div style={styles.circle}></div>
解决方案是将一个空对象传递给 Object.assign()。通过这样做,您就是在告诉该方法使用您传递给它的对象生成一个 新对象 。
示例 3:
const obj1 = {
name: "J"
}
const obj2 = {
gander: "m"
}
// Here, obj1 is the same after the Object.assign call
console.log(Object.assign({}, obj1, obj2));
console.log(obj1)
console.log(obj2)
console.log("without empty obj passed")
// Note that after this call, obj1 holds both keys. So this will mutate it:
console.log(Object.assign(obj1, obj2));
console.log(obj1) // This is different now
console.log(obj2)
在您的情况下,
`<A propstyle={{background: '#fe6969', color: '#fff'}} />
<A propstyle={{background: '#ff8137', color: '#fff'}} /> `
组件 A 在父级中定义了两次,这意味着我们将得到两个圆圈,子组件将渲染两次。
在子组件中,您定义如下:
<span style={Object.assign(elementStyle , style) }{...other}>{label}</span>
第一次渲染:
Object.assign 从右到左将 props
style
覆盖为 elementStyle,这里 elementStyle 本身是目标对象,它将是从 Object.assign 返回的内容。
样式属性:
{ background:“#fe6969”, color:“#fff” }
elementStyle:
{ background:“#fe6969”, borderRadius:“10px”, color:“#fff” }
第二次渲染:
Object.assign 尝试从右到左覆盖属性,但 elementStyle 有
{ background:“#fe6969”, borderRadius:“10px”, color:“#fff” }
并且 Object.assign 仍然在循环中(记住示例 1 .map())
样式属性:
{ background:“#ff8137”, color:“#fff” }
抛出错误:'TypeError:无法分配给对象的只读属性'background'
{Object.assign(elementStyle , style) }code> 因为没有新的目标对象。
请在 此处 找到完整代码
希望对您有所帮助。 阅读更多
不要直接为对象赋值,而是先克隆对象,而不是改变由于对象是 props 对象或因为使用 Object.defineproperties 将 writable 设置为“false”而导致的不可变对象,而只是克隆对象并将值分配给克隆的对象并使用克隆的对象,但也要正确地将值分配给克隆的对象。
不要像这样直接分配和变异:
object.field = value
请执行以下操作:
let clonedObject = {...object}
clonedObject = {...clonedObject, field: value}
否则,使用 object.defineproperties 将 writable 属性设置为“true”也可能是另一种可行的方法。
Object.defineProperty(object, 'field1', {
value: 1,
writable: true
});