React Base Fiddle (JSX)

Starting point for creating JSFiddles with React.

by Abdul Ahmad

HTML

<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="container">
    <!-- This element's contents will be replaced with your component. -->
</div>

SCSS

html {
  height: 100%;
}

body {
  margin: 0;
  height: 100%;
  font-family: sans-serif;
}

#container {
  height: 100%;
  background: #eee;
  text-align: center;
  overflow-y: auto;
  padding-bottom: 40px;
  border: 1px solid red;
}

%std-padding {
  box-sizing: border-box;
  padding: 30px 30px 20px;
}

%card {
  @extend %std-padding;
  background: white;
  display: inline-block;
  margin: 5px;
  border-radius: 3px;
  overflow: hidden;
  width: 300px;
  vertical-align: top;
  border: 1px solid #ddd;
}

.loading {
  @extend %card;
  
  img {
    border-radius: 10px;
    width: 90%;
    height: auto;
    margin-bottom: 10px;
    background-size: cover;
  }
}

.topping-combo {
  @extend %card;
  
  padding: 0;
}

.topping-combo__header {
  @extend %std-padding;
  text-align: left;
  font-size: 25px;
  font-weight: 100;
}

.topping-combo__header-rank {
  color: teal;
  font-weight: normal;
}

.topping-combo__info {
  @extend %std-padding;
  padding-top: 0;
  text-align: left;
}

.topping-combo__info-group {
  margin-top: 20px;
  
  &:first-child {
    margin-top: 0;
  }
  
  b {
    color: rgba(black, 0.8);
    font-size: 14px;
  }
  
  div {
    font-size: 14px;
    color: rgba(black, 0.8);
  }
}

Babel + JSX

// - using ES6

// - assuming no redux - state managed by component
class TopTwentyPizzaToppings extends React.Component {
  state = {
    topTwentyToppingCombos: undefined,
  }

  constructor(props) {
    super(props);
  }

  componentDidMount() {
    fetch('http://files.olo.com/pizzas.json').then((res) => {
    	return res.json();
    }).then((res) => {
    	this.getTop20ToppingCombos(res);
    });
  }
  
  getTop20ToppingCombos(orders) {
  	const categorizedOrders = this.categorizeOrders(orders);
    const rankedCategories = this.rankCategories(categorizedOrders);
    let top20 = rankedCategories.slice(0, 20);
    
    this.setState({ topTwentyToppingCombos: top20 });
  }
  
  categorizeOrders(orders) {
  	const categorizedOrders = {};
    
  	orders.forEach((order) => {
      let alphabetizedToppings = order.toppings.sort();    
      const toppingCombo = alphabetizedToppings.join(', ');
      const toppingComboItem = categorizedOrders[toppingCombo];

      if (toppingComboItem) {
        const numberTimesOrdered = toppingComboItem.numberTimesOrdered;
        categorizedOrders[toppingCombo].numberTimesOrdered = numberTimesOrdered + 1;
      } else {
      	// - store both number of times ordered and the actual toppings,
        //   this will save a loop or two in the future
      	categorizedOrders[toppingCombo] = { 
        	numberTimesOrdered: 1, toppings: toppingCombo 
        };
      }
    });
    
    return categorizedOrders;
  }
  
  rankCategories(orders) {
    return Object.values(orders).sort(
      (a, b) => b.numberTimesOrdered - a.numberTimesOrdered
    );
  }

  render() {
  	const { topTwentyToppingCombos } = this.state;
    
    if (topTwentyToppingCombos) {
    	const toppingCombos = topTwentyToppingCombos.map(
        (toppingCombo, index) => {
        	return <ToppingCombo key={index} index={index} data={toppingCombo} />;
        }
      );
      
    	return toppingCombos;
    };
  
    return (
      <Loading />
    );
  }
}

function...