Ilia-DK
Ilia-DK

Reputation: 45

Common toggle function doesn't work well with setState()

I have a state which represents this interface:

StateInterface {
  variableOne: string;
  variableTwo: boolean;
  variableThree: boolean; 
  // ...
}

And toggle function:

toggleFunction = (value: keyof StateInterface): void => {
  this.setState((state) => ({
    [value]: !state[value]
  }));
};

Not all variables are boolean in my state

But TSLint is telling me that the function is missing some properties. Is it possible to use only one toggle function for my state?

Upvotes: 0

Views: 119

Answers (4)

Ilia-DK
Ilia-DK

Reputation: 45

I don't know why, but it works:

this.setState((state) => ({
  ...state,
  [value]: !state[value],
}));

Without ...state I get an error about missing fields

Upvotes: 0

Juraj Kocan
Juraj Kocan

Reputation: 2878

so what about to make your function to only accpet keys that are boolean in your interface?

interface IStateInterface {
  variableOne: string;
  variableTwo: boolean;
  variableThree: boolean;
  // ...
}

// here you make type filtered type
type FilterType<Base, Condition> = {
  [Key in keyof Base]:
  Base[Key] extends Condition ? Key : never
};

// so this is type where all type that don't go throught condition are "never"
type filteredState = FilterType<IStateInterface, boolean>;  

and here just pick the keys
type allowedKeys = filteredState [keyof filteredState];

so in your function you have

toggleFunction = (value: allowedKeys ): void => {
  this.setState((state) => ({
    [value]: !state[value]
  }));
};

playground

Upvotes: 1

Ethan Vu
Ethan Vu

Reputation: 2987

for setState method we have 2 options for using:

In your case, you used function, so which will be mutated only property not for all state's properties.

You can try to use this code:

toggleFunction = (value: keyof StateInterface): void => {
  this.setState((state) => {
    value.forEach(property => {
    if( typeof(state[property]) != 'string'){ 
    state[property]= !state[property]
    }
  });
  return state;
};

Upvotes: 0

Prashant Adhikari
Prashant Adhikari

Reputation: 63

Could you please more elaborate the query more specifically about what your toggle function will do.

From above toggle function I can see that you are changing the state of a boolean state variable.

What about variableOne which is string.

For your case you have to setState conditional based on the value.

If-else might work to check value is boolean or not.

toggleFunction = (value: keyof StateInterface): void => {
   if (typeof variable === "boolean") 
{
  this.setState((prevState) => ({
    [value]: !prevState[value]
  }));
} else {
   this.setState((prevState) => ({
    [value]: 'Some value'
  }));
}

};

Upvotes: 0

Related Questions