Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to clear/remove state properties? #962

Closed
realbugger opened this issue Feb 26, 2016 · 13 comments
Closed

How to clear/remove state properties? #962

realbugger opened this issue Feb 26, 2016 · 13 comments

Comments

@realbugger
Copy link

Still learning React JS and Redux, and found this boilerplate to be extremely helpful. Good job Erik!

I'm wondering how to clear/remove a state property, say, state.data. Note that I don't want to just set state.data to null. I want to remove state.data property all together. The following code works for me.

.......
case CLEAR:
      delete state.data;
      return {
        ...state,
        loading: false,
        loaded: false
      };
.......

However, my understanding is that state in Redux should not be mutated. Although it's working, doesn't it violate the immutable rule of Redux? Actually, I don't see any code in the example making copies of state object before changing it, like most other Redux implementation does (see below).

......
  var newState = Object.assign({}, state);
  newState.data= action.data;
  return newState;
......

So how does the example code get away from the whole Object.assign thing? I must be missing something. Thanks.

@bhj
Copy link

bhj commented Feb 26, 2016

Although it's working, doesn't it violate the immutable rule of Redux?

Yes, the delete statement is mutating the previous state. You'll probably find this breaks time travel/undo/redo, which are core benefits of Redux to be ignored at your own peril!

I don't see any code in the example making copies of state object before changing it

That's what ...state is doing (copying the properties of the previous state to the new object literal that gets returned). It's an ES7 object spread initializer and I believe it does get transpiled down to Object.assign after Babel has its way with it.

Of course, whether deleting the data property altogether is actually a good idea or not is very debatable. I'd highly recommend rethinking this and keeping your state shapes consistent.

@realbugger
Copy link
Author

Got it. That makes sense. Thanks a lot.

@sebkouba
Copy link

sebkouba commented May 16, 2016

My google search pointed me here and the answer above seemed vague. How about the following as implementation to removing keys...

It filters the key that should be deleted then builds a new object from the remaining keys and the initial object. The idea is stolen from Tyler McGinnes awesome reactjs program.

function removeByKey (myObj, deleteKey) {
  return Object.keys(myObj)
    .filter(key => key !== deleteKey)
    .reduce((result, current) => {
      result[current] = myObj[current];
      return result;
  }, {});
}

JSBin

@matyasfodor
Copy link

Another solution would be

function removeKey(myObj, deleteKey) {
  return Object.assign(
    {},
    ...Object.entries(myObj)
       .filter(([k]) => k!== deleteKey)
       .map(([k, v]) => ({[k]: v})));
}

@Halt001
Copy link

Halt001 commented Oct 31, 2017

Is there something wrong with:

function removeKey(obj, deleteKey) {
  let clone = Object.assign({}, obj);
  delete clone[deleteKey];
  return clone;
}

@BornaP
Copy link

BornaP commented Jan 30, 2018

@Halt001 If you change myObj parameter to obj so that function doesn't break, it's perfectly fine :)

@ghost
Copy link

ghost commented Feb 1, 2018

You can use destructuring to remove the properties.

Here is a function that I use in my validation reducers to return a valid field state after making sure that the validation passed. It removes the invalid and error fields from the given fieldState object.

function validFieldState(fieldState) {
  if (fieldState.invalid) {
    const {
      invalid: _invalid,    // <-- The `_invalid` and `_error` variables are never used.
      error: _error,
      ...nextFieldState,  // <-- This variable gets every prop except for `invalid` and `error`.
    } = fieldState;
    return nextFieldState;
  }
  return fieldState;
}

This is a common pattern used in React, to remove certain props before copying them to a child component.

@prufrock123
Copy link

The only headache with your approach @waynebloss, is that a lot of linters do not allow unused variables. You can always disable a rule temporarily, but that kind of inconsistency is not ideal. Especially in a production deployment.

Are there any other approaches besides the ones mentioned here?

@ghost
Copy link

ghost commented Mar 21, 2018

@prufrock123 I should have mentioned that the variables should be prefixed with an underscore as shown in my example, because the linter that is built into create-react-app will automatically ignore any unused variable that starts with an underscore.

This seems to be a common feature of other linters and I see it mentioned a few different places:

Couldn't find the official docs for tslint, but it should work.

Which linter are you using?

@ghost
Copy link

ghost commented Mar 21, 2018

@tyasink
Copy link

tyasink commented Dec 3, 2019

this code cleans all state variables

let cleanState = {};
Object.keys(this.state).forEach(x => cleanState[x] = null);
this.setState(cleanState);

@OreOlad
Copy link

OreOlad commented Jul 29, 2020

I don't think that there's anything wrong with that method.

@fiznool
Copy link

fiznool commented Sep 29, 2021

Since the introduction of destructuring and rest syntax to JavaScript, this can now be accomplished in another way:

const { data, ...rest } = state;
return {
  ...rest,
  loading: false,
  loaded: false
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants