3

I have a state that holds a list of items and checkboxes which are either assigned false or true by default (depending on the API I'm working with).

For simplicity let's say that I have my state like this.

state = { 
  list: [
    {
    id: 0,
    name: 'item1'
    assigned: true
    }
  ],
   dirtyList: []
}

When a checkbox is clicked, you press a button and the popup tells you if the item was registered or removed (checkbox is true/false). But let's say that you start the page with a checkbox already checked and then you click it two times (making it checked true again), the popup should not say that the item has been registered because the original state hasn't changed. (It went from true, false, then back to true)

Here is my checkbox handleChange function

checkboxChanged = (event, id) => {    
let isChecked = event.target.checked
const index = this.state.list.findIndex(list => list.id === id)
const newState = [...this.state.list]
let newList = { ...newState[index] }
console.log(newList) 
// By console logging this, it eventually tells me the previous state of the item that was clicked

newState[index].assigned = isChecked
this.setState({
  list: newState,
})
}

I'm having a hard time figuring out how/where I can update the 'dirtyList' state because only then I can compare the original state with the dirty one.

SmalliSax
  • 342
  • 3
  • 6
  • 24

3 Answers3

6

You could do it simpler. Create a startpoint and put that in your state. Mutate only the state and compare it to startState when you need to:

const startState = {
    a: true,
    b: false
}
this.state = this.startState;

onSomeAction(){
    if( JSON.stringify(startState) !== JSON.stringify(this.state){ /* ... */}
}

Read this page for Object comparison in Javascript.


Alternatively, you can just check on value:

onChange(key, evt){
    if( this.state[key] !== this.startState[key] ){ /* ... */ }
    // usage: this.onChange(event, 'a');
}
Martijn
  • 15,791
  • 4
  • 36
  • 68
  • This is a quick way to do it. But I would recommend using libraries like https://www.npmjs.com/package/immer – Praveen Jan 14 '19 at 09:31
1

According to the React Documentation

Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.

this.setState((state)=>{
   // some code here

   const newState = [...state.list]
   return {
      list: newState
   }
})
lomse
  • 4,045
  • 6
  • 47
  • 68
1

This is how i checked if the text field is dirty.

const [fullName, setFullName] = useState({name: '', dirty: false})
.....
const showError = () {
   return fullName.dirty && isEmpty(fullName.name) //<- lodash isEmpty
}
<TextInput
   ...
   onChangeText={(names) => {setFullName({name: names, dirty: true})}}
   ...
/>
Dharman
  • 30,962
  • 25
  • 85
  • 135
Charz
  • 41
  • 4