未捕获的类型错误:无法分配给对象“#<Object>”的只读属性“”

kek*_*eee 6 reactjs babeljs

我不知道这段代码有什么区别。类 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;
Run Code Online (Sandbox Code Playgroud)

示例代码是 example.js

import A from './A';

    export default class Example extends React.Component {
        render() {
            return (
                <div>
                    <A style={{background: '#fe6969', color: '#fff'}} /> &nbsp;
                    <A style={{background: '#ff8137', color: '#fff'}} /> &nbsp;
                    <A  style={{background: '#fcb400', color: '#fff'}} /> &nbsp;
                </div>
            );
        }
    }
Run Code Online (Sandbox Code Playgroud)

此代码错误是未捕获的类型错误:无法分配给对象“#”的只读属性“背景”

我使用 babel-loader 8、babel7、webpack4

如果我正确 Object.assgin({}, elementStyle, style) 正在工作。我认为在重新渲染 A 组件时会发生此错误。我不知道为什么这个错误...

请帮我。

Jay*_*vel 13

您需要做的就是使用 spread 连接/合并两个这样的对象

{{...elementStyle, ...style}}  or

{Object.assign({}, elementStyle , style) }
Run Code Online (Sandbox Code Playgroud)

您应该了解 Object.assign 的工作原理。它返回目标对象作为其操作的返回值。

所以,在第一个语法中:

Object.assign({}, elementStyle , style)
Run Code Online (Sandbox Code Playgroud)

您正在使用 elementStyle 和 style 的可枚举属性创建一个全新的对象

如果你这样做:

Object.assign(elementStyle, style)
Run Code Online (Sandbox Code Playgroud)

然后elementStyle 本身就是目标对象,因此它将被改变,这将是从 Object.assign 返回的内容。

这是我的意思的一个例子。

示例 1:

{{...elementStyle, ...style}}  or

{Object.assign({}, elementStyle , style) }
Run Code Online (Sandbox Code Playgroud)

示例 2:

var styles =  {
  circle: {backgroundColor: 'yellow', height: '1005', width: '100%'},
  circleA: {backgroundColor: 'blue'},
};
Run Code Online (Sandbox Code Playgroud)

所以我们需要所有圆都有默认的圆某种圆样式,但我们需要改变一些属性,

// 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>
Run Code Online (Sandbox Code Playgroud)

解决方案是将一个空对象传递给 Object.assign()。通过这样做,您告诉该方法使用您传递给它的对象生成一个NEW 对象

示例 3:

Object.assign({}, elementStyle , style)
Run Code Online (Sandbox Code Playgroud)

在你的情况下,

`<A propstyle={{background: '#fe6969', color: '#fff'}} />

<A propstyle={{background: '#ff8137', color: '#fff'}} /> ` 
Run Code Online (Sandbox Code Playgroud)

组件 A 在 Parent 中定义了两次,这意味着我们将得到两个圆并且子组件将渲染两次。

在您定义的子组件中,如下所示:

<span style={Object.assign(elementStyle , style) }{...other}>{label}</span>
Run Code Online (Sandbox Code Playgroud)

第一次渲染:

Object.assign 将属性从右到左的 props 覆盖style到 elementStyle,这里 elementStyle 本身就是目标对象,这将是 Object.assign 返回的内容。

风格道具: { background: "#fe6969", color: "#fff" }

元素样式: { 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' of object ',{Object.assign(elementStyle , style) }因为没有新的目标对象。

请在这里找到完整的代码

希望能帮助到你。阅读更多


Ahm*_*r11 5

不要直接给对象赋值,而是先克隆对象,而不是改变一个不可变的对象,因为该对象是一个 props 对象,或者因为使用了 Object.defineproperties 将 writable 设置为“false”,但只是克隆对象并将值分配给克隆对象并使用克隆对象,但也要正确地将值分配给克隆对象。

而不是像这样直接分配和变异:

object.field = value
Run Code Online (Sandbox Code Playgroud)

做:

let clonedObject = {...object}
clonedObject = {...clonedObject, field: value}
Run Code Online (Sandbox Code Playgroud)

否则,使用 object.defineproperties 将可写属性设置为“true”也可能是另一种可行的方法。

Object.defineProperty(object, 'field1', {
  value: 1,
  writable: true
});
Run Code Online (Sandbox Code Playgroud)