Reputation: 1167
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
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
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
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