-1
\$\begingroup\$

My code is as follows :

import React, {PropTypes} from 'react';
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
import { filter_names } from './filterActions';
import Price from './price';
import Year from './year';
import Make from './make';
import Model from './model';
import Mileage from './mileage';
import Transmission from './transmission';
import Fuel from './fuel';

class filters extends React.Component {

    showFilters(filters){

        return filters.map(filter => {
            switch (filter.name){
                case filter_names.priceRange:
                    return <Price recap={filters.some(f => f.name === filter_names.priceRange)} title="Price" filters={filters} {...this.props}/>;
                case filter_names.year:
                    return <Year recap={filters.some(f => f.name === filter_names.year)} title="Year" filters={filters} {...this.props}/>;
                case filter_names.mileage:
                    return <Mileage recap={filters.some(f => f.name === filter_names.mileage)} title="Mileage" filters={filters} {...this.props}/>;
                case filter_names.fuel:
                    return <Fuel recap={filters.some(f => f.name === filter_names.fuel)} title="Fuel" filters={filters} {...this.props}/>;
                case filter_names.transmission:
                    return <Transmission recap={filters.some(f => f.name === filter_names.transmission)} title="Transmission" filters={filters} {...this.props}/>;
                default:
                    return true;
            }
        })
    }


    render(){
        const language = this.props.language;
        const filters = this.props.filters;

        return (
            <div className="filters noPadding col-xl-8 col-lg-6 col-md-6 col-sm-5 col-xs-12">
                <ReactCSSTransitionGroup transitionName="example" transitionAppear={true} transitionAppearTimeout={500} transitionEnterTimeout={500} transitionLeaveTimeout={500}>
                    {this.showFilters(filters)}
                </ReactCSSTransitionGroup>
            </div>
        );
    }

}

export default filters;

Is there any way to write it on a cleaner way? I have in showFilter function all those components. Do I need to repeat it for every component or is there any simpler way to do it?

\$\endgroup\$
  • 2
    \$\begingroup\$ We all want to write cleaner code so please write in the title what your code does. What you want is implicit on this site. \$\endgroup\$ – t3chb0t Sep 12 '16 at 12:47
3
\$\begingroup\$

You haven't shown any of the child components, but here's how I would approach this:

Instead of having each of your components be generated in a giant switch statement, I'd use an object that maps a component name to a component itself. Each of these components all have the same prop keys, they are just different components, right? *

Further, your recap value is completely pointless. If you're on that switch branch you don't need to do a some on the filter array to check if at least one element exists in the array with that name - you already know it does, because you're on that switch branch. As a result, I can simplify your showFilters method to:

const filterComponentMap = {
  priceRange: (props) => <Price title='Price' {...this.props} />
}

showFilters(filters, originalProps) {
  return filters.map((filter) => {
    return filterComponentMap[filter.name]({ filters, ...originalProps })
  }
}

You don't include the declaration of filter_names, but if you wanted to use the keys of those rather than raw strings you could always do:

const filterComponentMap = {
  [filter_actions.priceRange]: (props) => ..
}

Note that by convention we name variables camelCase and not snake_case, so rename that filter_actions to filterActions. Classes should be named PascalCase, and component should always follow that convention (even though components aren't always classes), so filters should be Filters (which is not a particularly good description either, by the way).

As your component is stateless there's no need to have the boilerplate of extending it from React.Component, you can instead use a simple function:

function showFilters(filters, originalProps) {
  ...
}

const Filters = ({ language, filters }) => {
  return <div className="filters noPadding col-xl-8 col-lg-6 col-md-6 col-sm-5 col-xs-12">
    <ReactCSSTransitionGroup transitionName="example" transitionAppear={true} transitionAppearTimeout={500} transitionEnterTimeout={500} transitionLeaveTimeout={500}>
      {showFilters(filters, this.props)}
    </ReactCSSTransitionGroup>
  </div>
}

export default Filters

Consider using SASS (or some other preprocessor) and name your classes based on the component itself rather than the properties of the class. That is, instead of adding .col-xs-8 .col-md-6 to your component declaration, add a single class to it (named .filters or something, using BEM or whatever you want to use - I prefer CSS modules) and style it in SASS with the Bootstrap mixins like so:

.filters {
  @extend make-col($grid-breakpoints.md, 6);
  @extend make-col($grid-breakpoints.xs, 8);
}

And store this file alongside the component file named <ComponentName>.sass.


* note that this could be further simplified by doing something like this instead (for some values of simplified)

const filterComponentMap = {
  priceRange: Price
}

showFilters(filters, originalProps) {
  return filters.map((filter) => {
    return <{filtersComponentMap[filter.name]} filters={filters} {...originalProps} />
  }
}

But this feels almost generic to a fault and breaks down as soon as you want to add some unique props (boolean values, for instance) to any of your components.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.