AGrush
AGrush

Reputation: 1167

Setting state issue in react

I'm just learning React by making an app that searches available domain names and am reaching a point where i want to make it more complex.. however i think my setState inside one of my functions is very clunky and am pretty sure its a performance issue to continue with it in this form.

The function that I'm having difficulty with is onChangeWord, which runs every time the user types anything into the input boxes. It's currently working with a map function, so each time the user types, it modifies the words state array, all the other words that are unmodified in the array it also resets using a map function & if statement. Now I am wanting to add synonyms to each word (sometimes 200+ for each word..) so I don't think I'm doing this right.. It's mapping over every single word and bit of state every time a letter is typed.. surely there's a better way..

Is there a way of cleaning up my onChangeWord function and/or changing the way the words state is structured so that this function can be cleaner?

/// ControlPanel.js ///
export default class ControlPanel extends Component {
  state = {
    words: 
    [
      { 
        word: "",
        id: 1,
        column: 1,
        // synonymns: {
        //   all:[],
        //   selected:[]
        // }
      },
      { 
        word: "",
        id: 2,
        column: 2,
        // synonymns: {
        //   all:[],
        //   selected:[]
        // }
      }
    ]
  }

  onChangeWord = (columnId, e) => {
    const { words } = this.state
    const newWords = []
    words.map(word => {
      if(word.id == e.target.id){
        newWords.push( {word: e.target.value, id: word.id, column: columnId} ) 
      } else {
        newWords.push( {word: word.word, id: word.id, column: word.column} ) 
      } return null;
    })
    this.setState ({words: newWords})
  }

  // onAddWord = id => {...}
  // onRemoveWord = id => {...}
  // combineWords() {
  // ...etc
  // render() {...}
}

//////////////

/// WORD.js //

const Word = ({onRemoveWord, wordId, onChangeWord, columnId}) => {
  return (
    <div>
       <input 
          type="text"
          name="word" 
          id={wordId} 
          onChange={(e) => onChangeWord(columnId, e)} 
        /> 
        <span onClick={() => {onRemoveWord(wordId)}} className="deletebtn">-</span>
    </div>
  )
}

/////////////

Upvotes: 2

Views: 63

Answers (3)

Hagai Harari
Hagai Harari

Reputation: 2877

Hope its helpful

Do notice that you might not need to send columnId, and you maybe get it from ...w


    onChangeWord = (columnId, e) => this.setState ({
             words: this.state.words.map(w => w.id == e.target.id 
                ? {...w, word: e.target.value, column: columnId} 
                : w
   })

Upvotes: 1

possum
possum

Reputation: 2927

Is a word with a fixed id always in the same column? If so, you can store words by columns and just run the map over that subset. For "type something and update" inputs in the past, I've used onBlur rather than onChange which will occur when the cell loses focus rather than after something is typed.

If you want to update as they type, but not every keystroke and not necessarily when focus is lost, I'd then consider something doing an update on a timer which resets every time something is typed. That would give some buffer.

Upvotes: 1

gautamits
gautamits

Reputation: 1292

You are not using columnId to check for which word to identify.

refactor

onChangeWord = (columnId, e) => {
    const { words } = this.state
    const newWords = []
    words.map(word => {
      if(word.id == e.target.id){
        newWords.push( {word: e.target.value, id: word.id, column: columnId} ) 
      } else {
        newWords.push( {word: word.word, id: word.id, column: word.column} ) 
      } return null;
    })
    this.setState ({words: newWords})
  }

to

onChangeWord = (columnId, e) => {
    const { words } = this.state
    const newWords = words.map(word => {
      if(word.id === columnId){
        return {...word, 'word': e.target.value} 
      }
      return word
    })
    this.setState ({words: newWords})
  }

Upvotes: 1

Related Questions