简体   繁体   中英

Trying to update props in state with method in class component

I'm trying to render a closable tab bar using some Material UI components, and I'm having trouble implementing the onDelete method for when the user wants to close a tab. I'm passing the data set, an array of objects, as a prop called dataSet. I want to update it whenever the user closes a tab but it doesn't re-render; all tabs still appear. When I console.log this.state.dataSet on each click however, I see that the tabs are getting deleted. What am I doing wrong?

class ClosableTabs extends Component {
    state = {
      tabIndex: 0,
      dataSet: this.props.dataSet,
    };
    
    onDelete = id => {
       this.setState(prevState => {
         const updatedDataSet = prevState.dataSet.filter(tab => tab.id !== id);
         return {
           dataSet: updatedDataSet,
         };
       }, console.log(this.state.dataSet);
    };
    
    renderTabs = dataSet => {
     return dataSet.map(data => {
      return (
        <Tab
          key={data.id}
          label={
              <span>
                {data.title}
              </span>
              <Button
                icon="close"
                onClick={() => this.onDelete(data.id)}
              />
          }
        />
      );
    });
  };

  render() {
      const { value, dataSet, ...rest } = this.props;
    
      return (
        <TabBar value={this.state.tabIndex} onChange={this.onChange} {...rest}>
          {this.renderTabs(dataSet)}
        </TabBar>
      );
    }
  }

export default Tabs;

and here is my data set that I pass as props when I use <ClosableTabs />

const dataSet = [
  {
    id: 1,
    title: 'title 1',
  },
  {
    id: 2,
    title: 'title 2',
  },
  {
    id: 3,
    title: 'title 3',
  },
];

When you render dataSet, you use the array you get from props (which never changes):

render() {
      const { value, dataSet, ...rest } = this.props; // dataSet comes from props
    
      return (
        <TabBar value={this.state.tabIndex} onChange={this.onChange} {...rest}>
          {this.renderTabs(dataSet)} // renderTabs renders this.props.dataSet
        </TabBar>
      );
    }
  }

instead, render dataSet which comes from your state (you should use different naming for this.props.dataSet and this.state.dataSet to avoid this kind of mistakes):

render() {
      const { value, ...rest } = this.props;
      const { dataSet } = this.state; // dataSet now comes from state

      return (
        <TabBar value={this.state.tabIndex} onChange={this.onChange} {...rest}>
          {this.renderTabs(dataSet)} // renderTabs renders this.state.dataSet
        </TabBar>
      );
    }
  }

The problem is you are rendering the component with props instead of state. Your render function should look likes this:

render() {
      const { value, dataSet, ...rest } = this.props;
    
      return (
        <TabBar value={this.state.tabIndex} onChange={this.onChange} {...rest}>
          {this.renderTabs(this.state.dataSet)}
        </TabBar>
      );
    }
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM