如何在此React组件中修复“无法分配给对象的只读属性'样式”?

时间:2017-05-25 17:32:35

标签: javascript reactjs ecmascript-6 jsx

我正在创建一个自己的自定义标签组件。如果由标签标题组成,每个标题标题都有一个正文部分。单击选项卡标题时,相应正文的样式应设置为display:block,其他所有样式设置为display:none

由于某些原因,我收到此错误:

  

无法指定只读对象的属性“样式”

据我所知,我不允许手动改变样式属性,因为它似乎是只读的,但我该如何修复/解决这个问题?

这是我的代码:

Tabs.js

import React, { Component } from 'react';

class Tabs extends Component {

  constructor() {
    super();
    this.state = {
      activeIndex: 0,
    };
    this.tabHeads = [];
  }

  // Initial composition of tab heads
  componentWillMount() {
    React.Children.map(this.props.children, (el, i) => {
      const tab = el;
      const key = `tabKey${i}`;
      this.tabHeads.push((
        <div role="button" onClick={e => this.onTabClick(e, i)} key={key}>{tab.props.title}</div>
      ));
    });
  }

  // Called when user clicks a tab head
  onTabClick(e, i) {
    this.setState({ activeIndex: i });
  }

  render() {
    // Set display none or block for each tab
    React.Children.map(this.props.children, (el, i) => {
      const tab = el;
      let visibility = 'none';
      if (i === this.state.activeIndex) visibility = 'block';
      const newStyle = Object.assign({}, tab.props.style, { display: visibility });
      tab.props.style = newStyle;
    });

    return (
      <div style={this.props.style}>
        {this.tabHeads}
        {this.props.children}
      </div>
    );
  }
}

export default Tabs;

用法是这样的:

render() {
  const tabStyles = [
    { padding: '20px' }, // Tab 0
    { padding: '20px' }, // Tab 1
  ];

  <Tabs>

    <Tab style={tabStyles[0]} title="Tab1">
      <div>Content 1</div>
    </Tab>

    <Tab style={tabStyles[1]} title="Tab2">
      <div>Content 2</div>
    </Tab>

  </Tabs>
}

1 个答案:

答案 0 :(得分:7)

您尝试更改此行中的属性值:
 tab.props.style = newStyle;
但是React中的props是只读的,您无法手动更改其值。有关详细信息,请查看React docs 要修复它,您可以使用React.cloneElement,它允许使用将合并到现有属性中的新属性克隆元素:

render() {
    let childrenWithNewProps = React.Children.map(this.props.children, (el, i) => {
        let visibility = 'none';
        if (i === this.state.activeIndex) visibility = 'block';
        return React.cloneElement(el, {
               style: {
                 display: visibility
               }
           }
        )
    });

    return (
          <div style={this.props.style}>
            {this.tabHeads}
            {childrenWithNewProps}
          </div>
    );
}