Simple Kanban component I am looking for some suggestions on how to make my code cleaner and simpler. Or put another way: more elegant and idiomatic. Any other comments on quality or anything would be appreciated.

class App extends Component {
      constructor(props){
        super(props);

        this.state = {
            colIds : ["winnie", "bob", "thomas", "george"], 
            cols : [
              {name:"Winnnie", headerColor: "#8E6E95", id : "winnie" },
              {name:"Bob",  headerColor: "#39A59C", id :"bob"},
              {name:"Thomas",  headerColor: "#344759", id: "thomas"},
              {name:"George",  headerColor: "#E8741E", id: "george"}
            ],
            cards : [
              {colid: "winnie", task: "buy eggs"},
              {colid: "bob", task: "clean basement"},
              {colid: "thomas", task: "pack"},
              {colid: "george", task: "pay bills"},
            ]
          }

          this.addCard = this.addCard.bind(this);
          this.moveCardRight = this.moveCardRight.bind(this);
          this.moveCardLeft = this.moveCardLeft.bind(this);
      }

      getColCards(colid){
          let cards = this.state.cards.filter( c =&gt; c.colid == colid);
          return cards;
      }

      addCard(colid){
        let cardTask = window.prompt("Whats the task you want to add");
        let currentCards = this.state.cards.slice();
        let newCard = {colid: colid, task: cardTask};
        currentCards.push(newCard);
        this.setState({cards: currentCards});

      }
      moveCardRight(card){
        let currentCardCol = card.colid;
        let nextIndex =  this.state.colIds.indexOf(currentCardCol) + 1;

        if(nextIndex &gt; this.state.colIds.length - 1 ){
          return null;
        }
        let currentCards = this.state.cards.slice();
        for(let i = 0; i &lt; currentCards.length; i++){
            if(currentCards[i].task === card.task){
               currentCards[i] = {
                 ...currentCards[i],
                 colid : this.state.colIds[nextIndex]
               }
            }
        }
        this.setState({cards: currentCards});
      }

      moveCardLeft(card){
        let currentCardCol = card.colid;
        let nextIndex =  this.state.colIds.indexOf(currentCardCol) - 1;

        if(nextIndex &lt; 0 ){
          return null;
        }
        let currentCards = this.state.cards.slice();
        for(let i = 0; i &lt; currentCards.length; i++){
            if(currentCards[i].task === card.task){
               currentCards[i] = {
                 ...currentCards[i],
                 colid : this.state.colIds[nextIndex]
               }
            }
        }
        this.setState({cards: currentCards});
      }
      render() {
        let cols =[  
                      {name:"Winnnie", headerColor: "#8E6E95"},
                      {name:"Bob",  headerColor: "#39A59C"},
                      {name:"Thomas",  headerColor: "#344759"},
                      {name:"George",  headerColor: "#E8741E"}
        ];
        let colCards = this.state.cols.map(c =&gt; {
        let cards = this.getColCards(c.id).map(c =&gt;  {
            return &lt;div&gt;
                    &lt;span onClick = {() =&gt; this.moveCardLeft(c)}&gt; {"&lt;   "} &lt;/span&gt; 
                    {c.task}   
                    &lt;span onClick = {() =&gt; this.moveCardRight(c)}&gt; {"    &gt;"} &lt;/span&gt; 
                   &lt;/div&gt; 
          })

          return  &lt;CardCol  name={c.name}  headerColor={c.headerColor} addCard={this.addCard} id={c.id}&gt;
                     {cards}
                  &lt;/CardCol&gt;
        })
        return (
          &lt;div className="App"&gt;
          {colCards}
          &lt;/div&gt;
        );
      }
    }
Your implementation is great and works well, but there are some things you could change.

Eliminate repetitive code

You have two large methods, moveCardLeft and moveCardRight, that do almost the same thing. These can either be combined entirely or the matching code can be separated out to a new method and referenced by the original two. For my example, I chose the former:

moveCard(card, dir) {
  let nextIndex = this.state.colIds.indexOf(card.colid);

  if (dir === "left") nextIndex--;
  else if (dir === "right") nextIndex++;
  else return null;

  if (nextIndex &lt; 0 || nextIndex &gt; this.state.colIds.length - 1) {
    return null;
  }

  let currentCards = this.state.cards.slice();
  for (let i = 0; i &lt; currentCards.length; i++) {
    if (currentCards[i].task === card.task) {
      currentCards[i] = {
        ...currentCards[i],
        colid: this.state.colIds[nextIndex]
      }
    }
  }
  this.setState({ cards: currentCards });
}


With this, you just have to pass in an extra parameter for the direction (left or right). It eliminates the repetition which is almost always beneficial.

Use consistent formatting

This includes indentation, new lines, and general spacing.

As you have it written in your post (maybe this is just a copy/paste error), the map inside of a map in your render method is not indented properly, which will undoubtedly confuse you at some point. Here is what it should look like:

render() {
  let cols = [
    { name: "Winnnie", headerColor: "#8E6E95" },
    { name: "Bob", headerColor: "#39A59C" },
    { name: "Thomas", headerColor: "#344759" },
    { name: "George", headerColor: "#E8741E" }
  ];
  let colCards = this.state.cols.map(c =&gt; {
    let cards = this.getColCards(c.id).map(c =&gt; {
      return (
        &lt;div&gt;
          &lt;span onClick={() =&gt; this.moveCard(c, "left")}&gt;{"&lt;   "}&lt;/span&gt;
            {c.task}
          &lt;span onClick={() =&gt; this.moveCard(c, "right")}&gt;{"    &gt;"}&lt;/span&gt;
        &lt;/div&gt;
      );
    });

    return (
      &lt;CardCol name={c.name} headerColor={c.headerColor} addCard={this.addCard} id={c.id}&gt;
        {cards}
      &lt;/CardCol&gt;
    );
  });

  return (
    &lt;div className="App"&gt;
      {colCards}
    &lt;/div&gt;
  )
}


Other thoughts


Use strict equality (===) by default and only fall back to loose/abstract equality (==) when absolutely necessary.
Consider how much more concise your code could be if you got rid of the colIds and simply used the cols instead to organize the cards. Additionally, consider placing the cards inside of their respective cols instead of separating them out into their own object. I haven't tried this on your code, so it may end up being less concise, but it's good to consider various data structures in anything you write.