最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do I fix "Cannot assign to read only property 'style' of object" in this Reac

programmeradmin3浏览0评论

I am creating an own custom tab ponent. It consists of a tab header which each has a body part. When a tab header is clicked, the corresponding body's style should be set to display:block and all others to display:none.

For some reasons I am getting this error:

Cannot assign to read only property 'style' of object

I understand that I am not allowed to mutate the style property manually as it seems to be read-only but how do I fix/work around this?

Here is my code:

Tabs.js

import React, { Component } from 'react';

class Tabs extends Component {

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

  // Initial position of tab heads
  ponentWillMount() {
    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;

Usage is like this:

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>
}

I am creating an own custom tab ponent. It consists of a tab header which each has a body part. When a tab header is clicked, the corresponding body's style should be set to display:block and all others to display:none.

For some reasons I am getting this error:

Cannot assign to read only property 'style' of object

I understand that I am not allowed to mutate the style property manually as it seems to be read-only but how do I fix/work around this?

Here is my code:

Tabs.js

import React, { Component } from 'react';

class Tabs extends Component {

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

  // Initial position of tab heads
  ponentWillMount() {
    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;

Usage is like this:

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>
}
Share Improve this question edited May 12, 2021 at 7:36 Timo Ernst asked May 25, 2017 at 17:32 Timo ErnstTimo Ernst 16k25 gold badges113 silver badges174 bronze badges 2
  • You can't reassign a prop to a different value. Props are read-only. Re-evaluate your design. – Andrew Li Commented May 25, 2017 at 17:34
  • 2 "how do I fix/work around this?" Clone the child: facebook.github.io/react/docs/react-api.html#cloneelement – Felix Kling Commented May 25, 2017 at 17:34
Add a ment  | 

1 Answer 1

Reset to default 9

You try to change property value in this line:
tab.props.style = newStyle;
but props in React are read-only and you can't manually change their values. Please check React docs for more details.
To fix it you can use React.cloneElement which allow to clone element with new properties that will be merged into existing ones:

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>
    );
}
发布评论

评论列表(0)

  1. 暂无评论