Search code examples
javascriptreactjseslintdestructuring

Destructuring state/props in React


I'm learning React and I have Eslint installed in my project. It started giving me errors like

Use callback in setState when referencing the previous state. (react/no-access-state-in-setstate)
Must use destructuring state assignment (react/destructuring-assignment)

I tried to look this up but couldn't understand properly.

Can someone point me in the right direction with this?

Here is my code that throws the errors:

class LoginForm extends React.Component {
  state = {
    data: {
      email: "",
      password: "",
    },
    loading: false,
    errors: {},
  };

  onChange = e =>
    this.setState({
      data: { ...this.state.data, [e.target.name]: e.target.value },
    });

  onSubmit = () => {
    const errors = this.validate(this.state.data);
    this.setState({ errors });

    if (Object.keys(errors).length === 0) {
      this.setState({ loading: true });
      this.props
        .submit(this.state.data)
        .catch(err =>
          this.setState({
            errors: err.response.data.errors,
            loading: false,
          }),
        );
    }
  };
}

As I understand I would need to destructure this.state and this.props but how?

EDIT: After following the suggestions below, I ended up with this. All I need to fix right now is the props. Its asking me to use a destructuring props assignment.

onChange = ({ target: { name, value } }) =>
    this.setState(prevState => ({
        data: { ...prevState.data, [name]: value }
    }));

onSubmit = () => {
    const { data } = this.state;
    const errors = this.validate(data);
    this.setState({ errors });

    if (Object.keys(errors).length === 0) {
        this.setState({ loading: true });
        this.props
            .submit(data)
            .catch(err =>
                this.setState({ errors: err.response.data.errors, loading: false })
            );
    }
};

Thanks in advance and sorry for the newbie question.


Solution

  • What eslint is telling you with the react/destructuring-assignments error is that assignments like:

    const data = this.state.data;
    

    can be rewritten into:

    const { data } = this.state;
    

    This also works for function arguments, so:

    onChange = e => { ... }
    

    can be written as

    onChange = ({target: {value, name}}) => { ... }
    

    The next error for react/no-access-state-in-setstate tells you that you are writing:

    this.setState({
        data: { ...this.state.data, [e.target.name]: e.target.value }
    });
    

    when you should be writing:

    this.setState(prevState => ({
        data: { ...prevState.data, [e.target.name]: e.target.value }
    }));
    

    or, if you combine it with the react/destructuring-assignments rule:

    onChange = ({target: {name, value}}) =>
        this.setState(prevState => ({
            data: { ...prevState.data, [name]: value }
        }));
    

    You can read more about those two rules here:

    react/destructuring-assignment

    react/no-access-state-in-setstate