0

How do i accept conditional attributes in react.js

below is my search component, I want the InputGroup to have a onSubmit attribute if the onSubmit function is passed and an onChange attribute if an onChange function is passed

class QueryBar extends PureComponent {
  render() {
    const { placeholder, leftIcon, onSubmit, onChange, width } = this.props;
    return (
      <form
        style={{ width }}
        onSubmit={e => {
          e.preventDefault();
          onSubmit(e.target[0].value);
        }}
      >
        <InputGroup
          placeholder={placeholder}
          width={width}
          leftIcon="search"
          rightElement={
            <Button
              type="submit"
              icon={leftIcon}
              minimal={true}
              intent={Intent.PRIMARY}
            />
          }
        />
      </form>
    );
  }
}

QueryBar.propTypes = {
  width: PropTypes.number,
  placeholder: PropTypes.string,
  leftIcon: PropTypes.oneOfType(['string', 'element']),
  onSubmit: PropTypes.func
};

QueryBar.defaultProps = {
  placeholder: 'Search...',
  leftIcon: 'arrow-right',
  width: 360
};
export default QueryBar;
1
  • You shouldn't use conditional attributes but rather handle that in a function. In the function you can check the state of the input and based on that you can make the transformation as desired (update, change, submit, ..etc) Commented Jul 18, 2019 at 8:20

3 Answers 3

1

jsx elements can also accept objects. Initialize an object that contains information for both situations and then add a conditional to add a function if it exists in the props passed in.

render() {
    const { placeholder, leftIcon, onSubmit, onChange, width } = this.props;
    const inputGroupProps = {
    placeholder,
    width,
    leftIcon: 'search',
    rightElement: (
        <Button
        type="submit"
        icon={leftIcon}
        minimal={true}
        intent={Intent.PRIMARY}
        />
      )
    }
    if (onChange) {
    inputGroupProps.onChange = onChange
    }
    if (onSubmit) {
        inputGroupProps.onSubmit = onSubmit
    }
    return (
    <form
        style={{ width }}
        onSubmit={e => {
        e.preventDefault();
        onSubmit(e.target[0].value);
        }}
    >
        <InputGroup {...inputGroupProps} />
    </form>
    );
}

While I do not recommend it, adding both are technically OK because a prop that isn't passed in from the parent but destructured, will be undefined. I don't recommend this because it is not expressive and will probably confuse you in the future

<InputGroup
placeholder={placeholder}
width={width}
leftIcon="search"
rightElement={
    <Button
    type="submit"
    icon={leftIcon}
    minimal={true}
    intent={Intent.PRIMARY}
    />
}
onChange={onChange} // will be undefined and have no behavior if parent does not pass an onChange prop
onSubmit={onSubmit} // same for this one
/>
0

You can pass null if its not there i.e :

<InputGroup
          placeholder={placeholder}
          width={width}
          leftIcon="search"
          onChange={onChangeFn?onChangeFn:null} 
          onSubmit={onSubmitFn ? onSubmitFn : null}
          rightElement={
            <Button
              type="submit"
              icon={leftIcon}
              minimal={true}
              intent={Intent.PRIMARY}
            />
          }
        />

It will make sure if function is there then call function otherwise it will not anything.

4
  • I think it's better to use a logical expression which will express to false value. false is also not passed. Commented Jul 18, 2019 at 8:22
  • @FacyoKouch It can be. But Isn't its redundant as for only two condition we write same component twice?? Commented Jul 18, 2019 at 8:25
  • A logical expression is { onSubmitFn && onSubmitFn }. So using the && instead of the ?, so, no, I don't find it redundant at all Commented Jul 18, 2019 at 9:01
  • @FacyoKouch Ohh I understand different approach. It's also a good way. Commented Jul 18, 2019 at 9:03
0

I would do this:

The idea is to have an Object optionalProps, an empty object for any possible conditional properties, when a property exists, we add it to the object, then, in the InputGroup component we apply it as {...optionalProps} which will extract any added properties to the object, and return nothing if null.

we could follow another approach: onChange={onChange && onChange}

But, note This will return false as a value for cases where onChange doesn't exist.

  render() {
    const { placeholder, leftIcon, onSubmit, onChange, width } = this.props;
    let optionalProps = {};
    if(onChange){
      optionalProps['onChange'] = onChange;
    }
    if(onSubmit){
      optionalProps['onSubmit'] = onSubmit;
    }

    return (
      <form
        style={{ width }}
        onSubmit={e => {
          e.preventDefault();
          onSubmit(e.target[0].value);
        }}
      >
        <InputGroup
          placeholder={placeholder}
          width={width}
          leftIcon="search"
          {...optionalProps}
          rightElement={
            <Button
              type="submit"
              icon={leftIcon}
              minimal={true}
              intent={Intent.PRIMARY}
            />
          }
        />
      </form>
    );
  }

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.