1

Tried to do a map to set a value of selected to true and false but it doesn't change existing true value away, what's wrong?

selectTab = tab => e => {
    const { data } = this.state;
    this.setState(
      {
        data: data.map(o =>
          o.tab === tab ? { selected: true, ...o } : { selected: false, ...o }
        )
      },
      () => console.log(this.state.data)
    );
  };

https://codesandbox.io/s/885l8q537l

0

1 Answer 1

2

Try and spread the object first, and then add the selected property. Otherwise the selected property in o will overwrite it every time.

selectTab = tab => e => {
  this.setState(
    prevState => ({
      data: prevState.data.map(o =>
        o.tab === tab ? { ...o, selected: true } : { ...o, selected: false }
      )
    }),
    () => console.log(this.state.data)
  );
};

class App extends React.Component {
  state = {
    data: [
      {
        tab: 1,
        content: "Tab 1 content",
        selected: true
      },
      {
        tab: 2,
        content: "Tab 2 content"
      },
      {
        tab: 3,
        content: "Tab 3 content"
      }
    ]
  };

  selectTab = tab => e => {
    this.setState(
      prevState => ({
        data: prevState.data.map(o =>
          o.tab === tab ? { ...o, selected: true } : { ...o, selected: false }
        )
      }),
      () => console.log(this.state.data)
    );
  };
  
  render() {
    const { activeTab, data } = this.state;
    return (
      <div>
        {data.map(obj => (
          <div onClick={this.selectTab(obj.tab)}>{obj.tab}</div>
        ))}
        {data.map(obj => (
          <div>{obj.selected && obj.content}</div>
        ))}
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>

Sign up to request clarification or add additional context in comments.

4 Comments

wow nice catch, is there any case you would want to use spread at the end?
@DennisNgu: For object spread I can't think of any use-case, but if for array then yes const newArr = [...oldArr, newElement] vs const newArr = [newElement, ...oldArr]. It will change the ordering of element
@DennisNgu You most often want to create a new object with some property overriden, i.e. { ...o, selected: true}, but you might e.g. have an object with default values and potentially override them by putting the object at the end like const settings = { logLevel: 2, ...o };
@Tholle: Ha! I never thought it could be using it for default value! Brilliant thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.