5

I'm trying to build a 'put the words in order' typical language learning activity. The user is supposed to start by dragging the first word of a sentence to its right place and move on from there. Meanwhile, I'm checking whether the next word is in the right place. If so, that word/item changes CSS class and becomes not draggable and of a different background colour.

For this CSS class change to happen, I clone the draggable list of words, make the necessary changes and then I setState() with the new updated list. That's when I'm having problems. The list and the component will update occasionally, seems to be at random. I must be doing something wrong when I try to update the list of words in the handleDragEnd() method. Here's part of the code:

export default class Sentence extends Component {
  constructor(props) {
    super (props)
  
    // prepare this.state.list to be used by SortableJS
    let list = this.props.sentenceShuffled.map((word, index) => {
      return { id: (++index).toString(), name: word, class: 'sortable' }
    })

    this.state = {
      currentCorrectWord: 0, // stores how many words are correct already while student is sorting
      complete: false, // becomes true when sentence is sorted
      list: list // this object is used by SortableJS and is calculated in componentWillMount
    }
  
    this.handleDragEnd = this.handleDragEnd.bind(this)
  }

  handleDragEnd() {
    let currentCorrectWord = this.state.currentCorrectWord
    
    while ( this.state.list[currentCorrectWord].name === this.props.sentenceInOrder[currentCorrectWord]) {
      let newList = _.cloneDeep(this.state.list)
      newList[currentCorrectWord].class = 'notSortable'
      currentCorrectWord++

      /*
         this is where (I think) the problem is: setSate won't update states nor re-render component.
      */

      this.setState({ currentCorrectWord: currentCorrectWord })
      this.setState({ list: newList })

      ... more code here
    }
  }

  render() {
    return (
      ...more code here
            <ReactSortable
              list={this.state.list}
              setList={newState => this.setState({ list: newState })}
              filter=".notSortable"
            >
              {this.state.list.map(item => (
                <MDBBox 
                    className={item.class + ' eachWord'} 
                    key={item.id} 
                    onDragEnd={this.handleDragEnd} 
                    >{item.name}
                </MDBBox>
              ))}
            </ReactSortable>
      ...more code here
    )
  }
}

What am I doing wrong?

Padeti
  • 71
  • 4

0 Answers0