Kertix
Kertix

Reputation: 73

Reducing number of props

I have one component from where user can route to form. There are two options: create an new form or edit old one. I send all data with Link location to that form component. But because I have more than 8 fields, it gets messy to verify if location state exists or if there is no location state, use default values.

Currently I have something like that:

this.state = {
  firstName: this.props.location.state !== undefined ?
    this.props.location.state.userProfile.firstName : '',
  familyName: this.props.location.state !== undefined ?
    this.props.location.state.userProfile.familyName : '',
  address: this.props.location.state !== undefined ?
    this.props.location.state.userProfile.address : 'Enter your address',
  city: this.props.location.state !== undefined ?
    this.props.location.state.userProfile.city : 'Select your city',
  country: this.props.location.state !== undefined ?
    this.props.location.state.userProfile.country : 'Select your country',
  field: this.props.location.state !== undefined ?
    this.props.location.state.userProfile.field : '',
  message: this.props.location.state !== undefined ? 'Save my changes' : 'Create'
}

And this is received like that:

<Link to={{
  pathname: '/register/create', state: {
    userProfile: item <--comes from mapping
  }
}}>

Is there any better way to achieve it? Maybe just set main object as state and then setState's fields inside that one object?

Also using Context could be option, but as I read it shouldn't be used for just passing props to child's?

Upvotes: 0

Views: 203

Answers (3)

Prince Hernandez
Prince Hernandez

Reputation: 3731

I would rather deconstruct the object and have a default object in the case of any data

// this could be even outside of your class.
const defaultObj = {
  firstName: '',
  familyName: '',
  address: 'Enter your address',
  city: 'Select your city',
  country: 'Select your country',
  field: '',
}

/* the constructor*/

constructor(){
    const { userProfile = {} } = this.props.location.state || {};

    this.state = {
      ...defaultObj
      ...userProfile
    }
}

Upvotes: 1

dash
dash

Reputation: 387

The "select your city" shouldn't be in your state. It's better to just leave it empty and pass it to the form as {state.city || "select your city"}

JS:

if (this.props.location.state) {
const {firstName, familyName, address, country, field} = this.props.location.state.userProfile;

this.setState({firstName, familyName, address, country, field, message = 'Save my changes'})
}

JSX (view):

<p>City: {state.city || "select your city"}</p>
<p>Message: {state.message || 'Create'}</p>

Upvotes: 0

Źmicier Jaraševič
Źmicier Jaraševič

Reputation: 371

At least a point that is possible to simplify: in location.state stores an object and the local state can be filled from it directly:

this.state = this.props.location.state 
  ? this.props.location.state.userProfile
  : {
    firstName'',
    familyName: '',
    address: 'Enter your address',
    city: 'Select your city',
    country: 'Select your country',
    field: '',
  };

the message field looks like an unchangeable data, so it is better not to put it into the react state, but use a ternary operator in the render method

Upvotes: 1

Related Questions